LifeV
MeshUtility.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 Base utilities operating on meshes
30 
31  @contributor Tiziano Passerini <tiziano@mathcs.emory.edu>
32  @maintainer Tiziano Passerini <tiziano@mathcs.emory.edu>
33 
34  This file contains a set of base utilities used to test mesh entities or
35  operate on them
36  */
37 
38 #ifndef MESHUTILITY_H
39 #define MESHUTILITY_H 1
40 
41 
42 #include <algorithm>
43 #include <iterator>
44 
45 #include <boost/numeric/ublas/matrix.hpp>
46 #include <boost/numeric/ublas/io.hpp>
47 
48 
49 #include <lifev/core/LifeV.hpp>
50 #include <lifev/core/util/Switch.hpp>
51 #include <lifev/core/array/VectorSmall.hpp>
52 #include <lifev/core/mesh/MeshElementBare.hpp>
53 #include <lifev/core/mesh/MarkerDefinitions.hpp>
54 #include <lifev/core/mesh/MeshEntity.hpp>
55 #include <lifev/core/mesh/MeshEntityContainer.hpp>
56 #include <lifev/core/array/EnumMapEpetra.hpp>
57 
58 namespace LifeV
59 {
60 
61 namespace MeshUtility
62 {
63 /*
64  todo change the class names:
65  "EnquireBEntity --> EnquireBoundaryEntity" and so on
66  "GetCoordComponent --> GetCoordinatesComponent" and so on
67  */
68 
69 
70 //! A locally used structure, not meant for general use
71 typedef std::map < BareFace, std::pair<ID, ID >,
73 
74 //! A locally used structure, not meant for general use
75 typedef std::map < BareEdge, std::pair<ID, ID>,
77 
78 /*
79  *******************************************************************************
80  FUNCTORS
81  *******************************************************************************
82  */
83 //! @defgroup Predicates Some useful functors to be used to test mesh entities
84 
85 //! Functor to check if a Face is on the boundary
86 /*!
87  @ingroup Predicates
88 
89  This object uses the information contained in a FaceContainer produced
90  by findBoundaryFaces(). It does not use the information contained in the
91  mesh PointList, so it may be used to set up a proper mesh
92 
93  @pre boundaryFaceContainer has been previously set by a call to findBoundaryFaces()
94  */
95 template <typename MeshType>
97 {
98 public:
99 
100  //! @name Public Types
101  //@{
102  typedef MeshType mesh_Type;
103  typedef mesh_Type const* meshPtr_Type;
104  typedef typename mesh_Type::face_Type face_Type;
107  //@}
108 
109  //! @name Constructor & Destructor
110  //@{
111 
112  //! Constructor taking a mesh object and a face Entity
113  /*!
114  @param boundaryFaceContainer a container of boundary faces
115  @pre boundaryFaceContainer has been previously set by a call to findBoundaryFaces()
116  */
117  EnquireBFace ( temporaryFaceContainer_Type const& boundaryFaceContainer ) :
118  boundaryFaceContainerPtr ( &boundaryFaceContainer )
119  {}
120 
121  //! Virtual Destructor
122  virtual ~EnquireBFace()
123  {}
124  //@}
125 
126  //! @name Operators
127  //@{
128 
129  //! The function call operator
130  /*!
131  @param face a face entity in the mesh_Type
132  @return true if the face is on the boundary, false otherwise
133  */
134  bool operator() ( const face_Type& face ) const
135  {
136  ID point1Id, point2Id, point3Id, point4Id;
137  BareFace bareFace;
138 
139  point1Id = face.point ( 0 ).localId();
140  point2Id = face.point ( 1 ).localId();
141  point3Id = face.point ( 2 ).localId();
142  if ( faceShape_Type::S_numVertices == 4 )
143  {
144  point4Id = face.point ( 3 ).localId();
145  bareFace = ( makeBareFace ( point1Id, point2Id, point3Id, point4Id ) ).first;
146  }
147  else
148  {
149  bareFace = ( makeBareFace ( point1Id, point2Id, point3Id ) ).first;
150  }
151  return ( boundaryFaceContainerPtr->find ( bareFace ) != boundaryFaceContainerPtr->end() );
152  }
153 
154  //@}
155 private:
156  //! @name Private Methods
157  //@{
158 
159  //! Empty Constructor
161  {}
162  //@}
164 };
165 
166 
167 /*! Functor to check if an edge is on the boundary
168 
169  @ingroup Predicates
170 
171  This object uses the information contained in an EdgeContainer produced
172  by findBoundaryEdges(). It does not use the information contained in the mesh
173  PointList, so it differs from EnquireBEntity.
174 
175  @pre boundaryEdgeContainer has been previously set by a call to findBoundaryEdges()
176 
177  */
178 template <typename MeshType>
180 {
181 public:
182 
183  //! @name Public Types
184  //@{
185  typedef MeshType mesh_Type;
186  typedef mesh_Type const* meshPtr_Type;
187  typedef typename mesh_Type::edge_Type edge_Type;
189  //@}
190 
191  //! @name Constructor & Destructor
192  //@{
193 
194  //! Constructor taking a mesh object and an edge container
195  /*!
196  @param mesh a mesh object
197  @param boundaryEdgeContainer a container of boundary edges
198  */
199  EnquireBEdge ( temporaryEdgeContainer_Type const& boundaryEdgeContainer ) :
200  boundaryEdgeContainerPtr ( &boundaryEdgeContainer )
201  {}
202 
203  //! Copy Constructor
204  EnquireBEdge ( EnquireBEdge const& enquireBoundaryEdge ) :
205  boundaryEdgeContainerPtr ( enquireBoundaryEdge.boundaryEdgeContainerPtr )
206  {}
207 
208  //! Virtual Destructor
209  virtual ~EnquireBEdge()
210  {}
211  //@}
212 
213  //! @name Operators
214  //@{
215 
216  //! The function call operator
217  /*!
218  @param edge an edge entity in the mesh_Type
219  @return true if the edge is on the boundary, false otherwise
220  */
221  bool operator() ( const edge_Type& edge ) const
222  {
223  ID point1Id, point2Id;
224  BareEdge bareEdge;
225 
226  point1Id = edge.point ( 0 ).localId();
227  point2Id = edge.point ( 1 ).localId();
228  bareEdge = ( makeBareEdge ( point1Id, point2Id ) ).first;
229  return boundaryEdgeContainerPtr->find ( bareEdge ) != boundaryEdgeContainerPtr->end();
230  }
231 
232  //@}
233 private:
234  //! @name Private Methods
235  //@{
236 
237  //! Empty Constructor
239  {}
240  //@}
241 
243 };
244 
245 
246 /*! Functor to check if a mesh entity with boundary indicator is on the boundary
247 
248  @ingroup Predicates
249 
250  This objects works on mesh entities with boundary indicator (for instance a GeoPoint)
251  by enquiring its boundary flag. To be used only for checks.
252 
253  @warning It assumes that boundary indicators are correctly set.
254  */
255 template <typename MeshType>
257 {
258 public:
259 
260  //! @name Public Types
261  //@{
262  typedef MeshType mesh_Type;
264  //@}
265 
266  //! @name Constructor & Destructor
267  //@{
268 
269  //! Constructor taking a mesh object
270  /*!
271  @param mesh a mesh object
272  */
273  explicit EnquireBPoint ( mesh_Type& mesh ) : meshPtr ( &mesh )
274  {}
275 
276  //! Copy Constructor
277  EnquireBPoint ( EnquireBPoint const& enquireBoundaryPoint ) :
278  meshPtr ( enquireBoundaryPoint.meshPtr )
279  {}
280 
281  //! Virtual Destructor
282  virtual ~EnquireBPoint()
283  {}
284  //@}
285 
286  //! @name Operators
287  //@{
288 
289  //! The function call operator
290  /*!
291  @param MeshEntity a mesh entity with boundary indicator
292  @return true if the entity is on the boundary, false otherwise
293  */
294  bool operator() ( const MeshEntity& meshEntity ) const
295  {
296  return meshEntity.boundary();
297  }
298  //@}
299 
300 private:
301  //! @name Public Types
302  //@{
303 
304  //! Empty Constructor
306  {}
307  //@}
308 
310 };
311 
312 
313 /*! @ingroup Test_Functors
314 
315  @brief This functor is used to do some geometry checks.
316 
317  It is instantiated with the index of the component to be extracted from a vector
318  of geometric coordinates.
319  */
321 {
322 public:
323 
324  //! @name Constructor & Destructor
325  //@{
326 
327  //! Empty Constructor
329 
330  //! Constructor taking the component
331  /*!
332  @param i the index of the component to be extracted from a vector of geometric coordinates
333  */
334  explicit GetCoordComponent ( Int i );
335 
336  //! Copy constructor
337  GetCoordComponent ( const GetCoordComponent& getCoordComponent ) :
338  componentIndex ( getCoordComponent.componentIndex )
339  {}
340 
341  //! Virtual Destructor
342  virtual ~GetCoordComponent()
343  {}
344  //@}
345 
346 
347  //! @name Operators
348  //@{
349 
350  //! The function call operator
351  /*!
352  If componentIndex is valid (0 <= 2), the function call operator will operate on a vector
353  by returning a new vector of geometric coordinates, with the single
354  non null component corresponding to the componentIndex.
355 
356  Otherwise, the vector given as an argument will be returned unchanged.
357 
358  @param[in] x first component of the input vector
359  @param[in] y second component of the input vector
360  @param[in] z third component of the input vector
361  @param[out] ret output vector
362  */
363  void operator() ( Real const& x, Real const& y,
364  Real const& z, Real ret[ 3 ] ) const;
365 
366  //@}
367 private:
369 };
370 
371 
372 /*! @ingroup Test_Functors
373 
374  This functor is used to do some geometry checks.
375  It returns a vector of ones
376  */
377 class GetOnes
378 {
379 public:
380  //! @name Constructor & Destructor
381  //@{
382 
383  //! Empty Constructor
385  {}
386 
387  //! Copy Constructor
388  GetOnes ( const GetOnes& /* getOnes */ )
389  {}
390 
391  //! Virtual Destructor
392  virtual ~GetOnes()
393  {}
394  //@}
395 
396 
397  //! @name Operators
398  //@{
399 
400  //! The function call operator
401  /*!
402  @param[in] x first component of the input vector
403  @param[in] y second component of the input vector
404  @param[in] z third component of the input vector
405  @param[out] ret output vector (always a vector of ones)
406  */
407  void operator() ( Real const& x, Real const& y,
408  Real const& z, Real ret[ 3 ] ) const;
409  //@}
410 };
411 
412 
413 /*
414  *******************************************************************************
415  EDGES/FACES FINDERS
416  *******************************************************************************
417  */
418 
419 //! Finds mesh faces
420 /*!
421  A low level routine, not meant to be called directly. It creates a
422  container with all the information needed to set up properly the boundary
423  faces connectivities.
424 
425  @param mesh A 3D mesh.
426 
427  @param boundaryFaceContainer[out] This container will eventually contain a map whose key are
428  the BareFaces corresponding to the boundary faces; the map data are pairs of
429  IDs: the ID of the adjacent element and the relative position of the face
430  in the element. The search of boundary faces does not rely on the proper setting of boundary nodes.
431 
432  @param NumInternalFaces[out] A reference to an integer returning the number of internal faces found.
433 
434  @param[out] internalFaces A container that will possibly contain a map whose keys are
435  the BareFaces corresponding to internal faces and whose data are pairs of IDs:
436  the ID of the two elements adjacent to the face.
437 
438  @param buildAllFaces When this bool is set true the function will also construct the set
439  of internal faces, stored in internalFaces.
440 
441  @return Number of boundary faces found
442 
443  @note this method is intended to work on 3D meshes
444  */
445 template <typename MeshType>
446 UInt findFaces ( const MeshType& mesh, temporaryFaceContainer_Type& boundaryFaceContainer,
447  UInt& numInternalFaces, temporaryFaceContainer_Type& internalFaces,
448  bool buildAllFaces = false )
449 {
450  UInt point1Id, point2Id, point3Id, point4Id;
451  BareFace bareFace;
452  typename MeshType::elementShape_Type volumeShape;
453  typedef typename MeshType::volumes_Type volumeContainer_Type;
454  temporaryFaceContainer_Type::iterator faceContainerIterator;
455 
456  // clean first in case it has been already used
457  boundaryFaceContainer.clear();
458  if ( buildAllFaces )
459  {
460  internalFaces.clear();
461  }
462  numInternalFaces = 0;
463 
464  for ( typename volumeContainer_Type::const_iterator volumeContainerIterator = mesh.volumeList.begin();
465  volumeContainerIterator != mesh.volumeList.end(); ++volumeContainerIterator )
466  {
467  for ( ID jFaceLocalId = 0; jFaceLocalId < mesh.numLocalFaces(); ++jFaceLocalId )
468  {
469  point1Id = volumeShape.faceToPoint ( jFaceLocalId, 0 );
470  point2Id = volumeShape.faceToPoint ( jFaceLocalId, 1 );
471  point3Id = volumeShape.faceToPoint ( jFaceLocalId, 2 );
472  // go to global
473  point1Id = ( volumeContainerIterator->point ( point1Id ) ).localId();
474  point2Id = ( volumeContainerIterator->point ( point2Id ) ).localId();
475  point3Id = ( volumeContainerIterator->point ( point3Id ) ).localId();
476  if ( MeshType::facetShape_Type::S_numVertices == 4 )
477  {
478  point4Id = volumeShape.faceToPoint ( jFaceLocalId, 3 );
479  point4Id = ( volumeContainerIterator->point ( point4Id ) ).localId();
480  bareFace = ( makeBareFace ( point1Id, point2Id, point3Id, point4Id ) ).first;
481  }
482  else
483  {
484  bareFace = ( makeBareFace ( point1Id, point2Id, point3Id ) ).first;
485  }
486 
487  if ( ( faceContainerIterator = boundaryFaceContainer.find ( bareFace ) ) == boundaryFaceContainer.end() )
488  {
489  boundaryFaceContainer.insert (
490  std::make_pair ( bareFace, std::make_pair ( volumeContainerIterator->localId(), jFaceLocalId ) ) );
491  }
492  else
493  {
494  if ( buildAllFaces && point1Id > point2Id )
495  {
496  internalFaces.insert (
497  ( std::make_pair ( bareFace, std::make_pair ( volumeContainerIterator->localId(), jFaceLocalId ) ) ) );
498  }
499  boundaryFaceContainer.erase ( faceContainerIterator ); // counted twice: internal face
500  ++numInternalFaces;
501  }
502  }
503  }
504  return boundaryFaceContainer.size();
505 }
506 
507 
508 //! Finds boundary faces
509 /*!
510  A low level routine, not meant to be called directly. It creates a
511  container with all the information needed to set up properly the boundary
512  face connectivities.
513 
514  @param mesh A 3D mesh.
515 
516  @param boundaryFaceContainer[out] This container will eventually contain a map whose key are
517  the BareFaces corresponding to the boundary faces; the map data are pairs of
518  IDs: the ID of the adjacent element and the relative position of the face
519  in the element. The search of boundary faces does not rely on the proper setting of boundary nodes.
520 
521  @param numInternalFaces[out] A reference to an integer returning the number of internal faces found.
522 
523  @return Number of boundary faces found.
524 
525  @note this method is intended to work on 3D meshes
526  */
527 template <typename MeshType>
528 UInt findBoundaryFaces ( const MeshType& mesh,
529  temporaryFaceContainer_Type& boundaryFaceContainer,
530  UInt& numInternalFaces )
531 {
533  return findFaces ( mesh, boundaryFaceContainer, numInternalFaces, dummy, false );
534 }
535 
536 
537 //! Finds boundary edges
538 /*!
539  A low level routine, not meant to be called directly. It creates a
540  container with all the information needed to set up properly the boundary
541  edges connectivities.
542 
543  @param mesh A mesh.
544 
545  @param boundaryEdgeContainer[out] This container will eventually contain a map whose key are
546  the BareEdges corresponding to the boundary edges; the map data are pairs of
547  IDs: the ID of the adjacent face and the relative position of the edge
548  in the element. The search of boundary edges does not rely on the proper setting of boundary nodes.
549 
550  @return Number of boundary edges found.
551 
552  @pre The list of boundary faces in the mesh must be correctly set.
553  */
554 template <typename MeshType>
555 UInt findBoundaryEdges ( const MeshType& mesh, temporaryEdgeContainer_Type& boundaryEdgeContainer )
556 {
557  UInt point1Id, point2Id;
558  BareEdge bareEdge;
559  typedef typename MeshType::facetShape_Type facetShape_Type;
560  typedef typename MeshType::faces_Type faceContainer_Type;
561 
562 
563  if ( ! mesh.hasFaces() )
564  {
565  return 0;
566  }
567 
568  // clean first in case it has been already used
569  boundaryEdgeContainer.clear();
570 
571  // the following cycle assumes to visit only the boundary faces in mesh.faceList()
572  for ( typename faceContainer_Type::const_iterator faceContainerIterator = mesh.faceList.begin();
573  faceContainerIterator != mesh.faceList.begin() + mesh.numBFaces(); ++faceContainerIterator )
574  {
575  for ( ID jEdgeLocalId = 0; jEdgeLocalId < mesh.numLocalEdgesOfFace(); ++jEdgeLocalId )
576  {
577  point1Id = facetShape_Type::edgeToPoint ( jEdgeLocalId, 0 );
578  point2Id = facetShape_Type::edgeToPoint ( jEdgeLocalId, 1 );
579  // go to global
580  point1Id = ( faceContainerIterator->point ( point1Id ) ).localId();
581  point2Id = ( faceContainerIterator->point ( point2Id ) ).localId();
582  bareEdge = ( makeBareEdge ( point1Id, point2Id ) ).first;
583  boundaryEdgeContainer.insert (
584  std::make_pair ( bareEdge, std::make_pair ( faceContainerIterator->localId(), jEdgeLocalId ) ) );
585  }
586  }
587  return boundaryEdgeContainer.size();
588 }
589 
590 
591 //! Finds internal edges.
592 /*!
593  A low level routine, not meant to be called directly. It creates a
594  container with all the information needed to set up properly the edge
595  connectivities.
596 
597  @param mesh A 3D mesh.
598 
599  @param boundaryEdgeContainer[in] This container contains a map whose key are
600  the BareEdges corresponding to the boundary edges; the map data are pairs of
601  IDs (if generated from findBoundaryEdges(), those pairs will contain be the ID
602  of the adjacent mesh element and the relative position of the edge in the element).
603 
604  @param internalEdgeContainer[out] This container contains a map whose key are
605  the BareEdges corresponding to the boundary edges; the map data are pairs of
606  IDs: the ID of the adjacent element and the relative position of the edge
607  in the element.
608 
609  @return Number of edges found.
610 
611  */
612 template <typename MeshType>
613 UInt findInternalEdges ( const MeshType& mesh,
614  const temporaryEdgeContainer_Type& boundaryEdgeContainer,
615  temporaryEdgeContainer_Type& internalEdgeContainer )
616 {
617  UInt point1Id, point2Id;
618  BareEdge bareEdge;
619  typedef typename MeshType::elementShape_Type volumeShape_Type;
620  typedef typename MeshType::volumes_Type volumeContainer_Type;
621  temporaryEdgeContainer_Type temporaryEdgeContainer;
622 
623  ASSERT0 ( mesh.numVolumes() > 0, "We must have some 3D elements stored n the mesh to use this function!" );
624 
625  internalEdgeContainer.clear();
626  internalEdgeContainer.swap (temporaryEdgeContainer);
627 
628  for ( typename volumeContainer_Type::const_iterator volumeContainerIterator = mesh.volumeList.begin();
629  volumeContainerIterator != mesh.volumeList.end(); ++volumeContainerIterator )
630  {
631  for ( ID jEdgeLocalId = 0; jEdgeLocalId < mesh.numLocalEdges(); ++jEdgeLocalId )
632  {
633  point1Id = volumeShape_Type::edgeToPoint ( jEdgeLocalId, 0 );
634  point2Id = volumeShape_Type::edgeToPoint ( jEdgeLocalId, 1 );
635  // go to global
636  point1Id = ( volumeContainerIterator->point ( point1Id ) ).localId();
637  point2Id = ( volumeContainerIterator->point ( point2Id ) ).localId();
638  bareEdge = ( makeBareEdge ( point1Id, point2Id ) ).first;
639  if ( boundaryEdgeContainer.find ( bareEdge ) == boundaryEdgeContainer.end() )
640  internalEdgeContainer.insert
641  ( std::make_pair ( bareEdge, std::make_pair ( volumeContainerIterator->localId(), jEdgeLocalId ) ) );
642  }
643  }
644  return internalEdgeContainer.size();
645 }
646 
647 
648 /*
649  *******************************************************************************
650  MARKERS HANDLERS
651  *******************************************************************************
652  */
653 //! @defgroup marker_policies Used to manage missing handlers
654 
655 
656 /*! Sets the marker ID of a MeshElementMarked according to the policy of the marker
657 
658  @ingroup marker_policies
659 
660  It gets the stronger marker of the MeshElementMarked points. The marker
661  hierarchy is defined in the MarkerDefinitions.hpp file. It returns the new
662  marker id for the MeshElementMarked. If any of the vertices has an unset marker
663  the result is an unset marked ID for the MeshElementMarked.
664 
665  @sa MarkerDefinitions.hpp
666  @warning It overrides the original marker ID.
667  @return the new marker ID for geoElement
668 
669  @todo LF: It should be made a functor so to give the user a easier way
670  to change the policy if needed
671  */
672 
673 template <typename MeshElementMarkedType>
674 markerID_Type inheritPointsStrongerMarker ( MeshElementMarkedType& geoElement )
675 {
676  ASSERT_PRE ( MeshElementMarkedType::S_nDimensions > 0,
677  "A MeshElementMarked with ndim == 0 cannot inherit marker IDs" );
678 
679  geoElement.setMarkerID ( geoElement.point ( 0 ).markerID() );
680  for ( ID jPointId = 1; jPointId < MeshElementMarkedType::S_numVertices; ++jPointId )
681  {
682  geoElement.setStrongerMarker ( geoElement.point ( jPointId ).markerID() );
683  }
684  return geoElement.markerID();
685 
686 }
687 
688 
689 /*! @ingroup marker_policies
690 
691 //! @brief Sets the marker ID of a MeshElementMarked of dimension greater one
692 
693  It gets the weaker marker of the MeshElementMarked points. The marker
694  hierarchy is defined in the MarkerDefinitions.hpp file. It returns the new
695  marker id for the MeshElementMarked. If any of the vertices has an unset marker
696  the result is an unset marker ID for the MeshElementMarked.
697 
698  @sa MarkerDefinitions.hpp
699  @warning It overrides the original marker ID.
700  @return the new marker ID for geoElement
701  */
702 template <typename MeshElementMarkedType>
703 markerID_Type inheritPointsWeakerMarker ( MeshElementMarkedType& geoElement )
704 {
705  ASSERT_PRE ( MeshElementMarkedType::S_nDimensions > 0,
706  "A MeshElementMarked with ndim == 0 cannot inherit marker IDs" );
707 
708  geoElement.setMarkerID ( geoElement.point ( 0 ).markerID() );
709  for ( ID jPointId = 1; jPointId < MeshElementMarkedType::S_numVertices; ++jPointId )
710  {
711  geoElement.setWeakerMarkerID ( geoElement.point ( jPointId ).markerID() );
712  }
713  return geoElement.markerID();
714 
715 }
716 
717 
718 /*!
719  This routine tests if the topological description of boundary face is sane.
720  In particular all boundary edges must be adjacent to only 2 surface elements
721  and the orientation must be correct.
722 
723  @param mesh a mesh
724  @param numBoundaryEdges The function also returns the number of boundary edges in numBoundaryEdges.
725 
726  @return It it returns 0 if the test has been passed. If not it returns the number of wrong boundary edges.
727  @warning numBoundaryEdges is properly set only if the test has been passed.
728  */
729 template <typename MeshType>
730 UInt testDomainTopology ( MeshType const& mesh, UInt& numBoundaryEdges )
731 {
732 
733  typedef std::set <BareEdge, cmpBareItem<BareEdge> > localTemporaryEdgeContainer_Type;
734  localTemporaryEdgeContainer_Type localTemporaryEdgeContainer;
735  UInt point1Id, point2Id;
736  BareEdge bareEdge;
737  typename MeshType::facetShape_Type faceShape;
738  typedef typename MeshType::faces_Type faceContainer_Type;
739  typedef typename MeshType::face_Type face_Type;
740  localTemporaryEdgeContainer_Type::iterator edgeContainerIterator;
741 
742  typename faceContainer_Type::const_iterator faceContainerIterator = mesh.faceList.begin();
743 
744  for ( UInt kFaceId = 0; kFaceId < mesh.numBFaces(); ++kFaceId )
745  {
746  std::ostringstream errorStream;
747  errorStream << " Trying to get not existing face"
748  << kFaceId << " " << mesh.numBFaces();
749  ASSERT ( faceContainerIterator != mesh.faceList.end(), errorStream.str().c_str() );
750 
751  for ( ID jEdgeLocalId = 0; jEdgeLocalId < face_Type::S_numEdges; ++jEdgeLocalId )
752  {
753  point1Id = faceShape.edgeToPoint ( jEdgeLocalId, 0 );
754  point2Id = faceShape.edgeToPoint ( jEdgeLocalId, 1 );
755  // go to global
756  point1Id = ( faceContainerIterator->point ( point1Id ) ).localId();
757  point2Id = ( faceContainerIterator->point ( point2Id ) ).localId();
758  bareEdge = ( makeBareEdge ( point1Id, point2Id ) ).first;
759 
760  if ( ( edgeContainerIterator = localTemporaryEdgeContainer.find ( bareEdge ) )
761  == localTemporaryEdgeContainer.end() )
762  {
763  localTemporaryEdgeContainer.insert ( bareEdge );
764  ++numBoundaryEdges;
765  }
766  else
767  {
768  localTemporaryEdgeContainer.erase ( edgeContainerIterator );
769  }
770  }
771  ++faceContainerIterator;
772  }
773  return localTemporaryEdgeContainer.size();
774 }
775 
776 
777 /*
778  *******************************************************************************
779  MARKERS FIXING
780  *******************************************************************************
781  */
782 
783 //! Check whether all markers of a the geometry entities stored in a list are set
784 template <typename MeshEntityListType>
785 bool checkIsMarkerSet ( const MeshEntityListType& meshEntityList )
786 {
787  typedef typename MeshEntityListType::const_iterator MeshEntityListTypeConstIterator_Type;
788  bool ok ( true );
789  for ( MeshEntityListTypeConstIterator_Type meshEntityListIterator = meshEntityList.begin();
790  meshEntityListIterator != meshEntityList.end(); ++meshEntityListIterator )
791  {
792  ok = ( ok & meshEntityListIterator->isMarkerSet() );
793  }
794  return ok;
795 }
796 
797 
798 //! Sets the marker id for all boundary edges by inheriting them from boundary points.
799 /*!
800  The paradigm is that an edge <B>WHOSE MARKER HAS NOT ALREADY BEEN
801  SET</B> will get the WEAKER marker ID among its VERTICES. For instance
802  if a vertex is assigned to an Essential BC and the other to a Natural
803  BC the edge will get the marker ID related to the Natural B.C.
804 
805  What is a weaker marker is set in the MarkerPolicy passed through the markers.
806 
807  @param mesh A mesh
808  @param logStream stream to which a map edgeId -> TimeAdvanceNewmarker will be output
809  @param errorStream stream to which error messages will be sent
810  @param verbose if false, no messages will be sent to the logStream
811 
812  @todo it should take the way to handle missing marker ids as policy
813  @todo errorStream is unused
814  */
815 template <typename MeshType>
816 void
817 setBoundaryEdgesMarker ( MeshType& mesh, std::ostream& logStream = std::cout,
818  std::ostream& /*errorStream*/ = std::cerr, bool verbose = true )
819 {
820  verbose = verbose && ( mesh.comm()->MyPID() == 0 );
821 
822  typename MeshType::edge_Type* edgePtr = 0;
823  UInt counter ( 0 );
824 
825  if ( verbose )
826  logStream << "NEW EDGE MARKER MAP" << std::endl
827  << " ID->New Marker" << std::endl;
828 
829  for ( ID kEdgeId = 0; kEdgeId < mesh.numBEdges(); ++kEdgeId )
830  {
831  edgePtr = & ( mesh.edge ( kEdgeId ) );
832  if ( edgePtr->isMarkerUnset() )
833  {
834  inheritPointsWeakerMarker ( *edgePtr );
835  if ( verbose )
836  {
837  logStream << edgePtr->localId() << " -> " << edgePtr->markerID();
838  logStream << " ";
839  if ( ++counter % 3 == 0 )
840  {
841  logStream << std::endl;
842  }
843  }
844  }
845  }
846  if ( verbose )
847  {
848  logStream << std::endl;
849  }
850 }
851 
852 
853 //! Sets the marker ID for all boundary faces by inheriting them from boundary points.
854 /*!
855  The paradigm is that a face <B>WHOSE MARKER ID HAS NOT ALREADY BEEN SET</B> will
856  get the WEAKER marker ID among its VERTICES. For instance if a vertex
857  is assigned to a Natural BC and the others to a Natural BC the face
858  will get the marker ID related to the Natural BC
859 
860  @param mesh A mesh
861  @param logStream stream to which a map faceId -> TimeAdvanceNewmarker will be output
862  @param errorStream stream to which error messages will be sent
863  @param verbose if false, no messages will be sent to the logStream
864 
865  @todo the way to handle missing IDs should be passed as a policy
866  */
867 template <typename MeshType>
868 void
869 setBoundaryFacesMarker ( MeshType& mesh, std::ostream& logStream = std::cout,
870  std::ostream& /*errorStream*/ = std::cerr, bool verbose = true )
871 {
872  verbose = verbose && ( mesh.comm()->MyPID() == 0 );
873 
874  typename MeshType::face_Type* facePtr = 0;
875  UInt counter ( 0 );
876 
877  if ( verbose )
878  {
879  logStream << "**** NEW FACE MARKER MAP **************" << std::endl;
880  logStream << " Face ID -> New Marker\tFace ID -> New Marker\tFace ID -> New Marker" << std::endl;
881  }
882 
883  for ( UInt kFaceId = 0; kFaceId < mesh.numBFaces(); ++kFaceId )
884  {
885  facePtr = & ( mesh.face ( kFaceId ) );
886  if ( facePtr->isMarkerUnset() )
887  {
888  inheritPointsWeakerMarker ( *facePtr );
889  if ( verbose )
890  {
891  logStream << facePtr->localId() << " -> " << facePtr->markerID();
892  logStream << "\t";
893  if ( ++counter % 3 == 0 )
894  {
895  logStream << std::endl;
896  }
897  }
898  }
899  }
900  if ( verbose )
901  {
902  logStream << std::endl;
903  }
904 }
905 
906 
907 //! It sets the marker ID for Points, by inheriting it from facets.
908 /*!
909  The paradigm is that a point whose marker ID is unset will inherit
910  the strongest marker ID of the surrounding facets, with the
911  convention that if the marker ID of one of the surrounding facets is null,
912  it is ignored.
913 
914  @param mesh A mesh
915  @param logStream stream to which a map PointId -> MarkerId will be output
916  @param errorStream stream to which error messages will be sent
917  @param verbose if false, no messages will be sent to the logStream
918  @pre The boundary faces must be correctly set and the points boundary flags as well
919  @note it does not touch _bPoints. It must be set otherwhise.
920  */
921 template <typename MeshType>
922 void
923 setBoundaryPointsMarker ( MeshType& mesh, std::ostream& logStream = std::cout,
924  std::ostream& /*errorStream*/ = std::cerr, bool verbose = false )
925 {
926  verbose = verbose && ( mesh.comm()->MyPID() == 0 );
927 
928  // First looks at points whose marker has already been set
929  std::vector<bool> isDefinedPointMarker ( mesh.storedPoints(), false );
930 
931  typedef typename MeshType::points_Type::iterator pointContainerIterator_Type;
932  typedef typename MeshType::facetShape_Type faceShape_Type;
933 
934  std::vector<bool>::iterator isDefinedPointMarkerIterator = isDefinedPointMarker.begin();
935 
936  for ( pointContainerIterator_Type pointContainerIterator = mesh.pointList.begin();
937  pointContainerIterator != mesh.pointList.end(); ++pointContainerIterator )
938  {
939  * ( isDefinedPointMarkerIterator++ ) = pointContainerIterator->isMarkerSet();
940  }
941 
942  typename MeshType::face_Type* facetPtr = 0;
943  for ( UInt kFacetId = 0; kFacetId < mesh.numBFaces(); ++kFacetId )
944  {
945  facetPtr = & ( mesh.boundaryFacet ( kFacetId ) );
946  if ( facetPtr->isMarkerSet() )
947  {
948  for ( UInt jPointId = 0; jPointId < faceShape_Type::S_numPoints; ++jPointId )
949  {
950  if ( !isDefinedPointMarker[ facetPtr->point ( jPointId ).localId() ] )
951  // A bit involved but it works
952  //todo operate directly on point using setStrongerMarkerID
953  {
954  facetPtr->setStrongerMarkerIDAtPoint ( jPointId, facetPtr->markerID() );
955  }
956  }
957  }
958  }
959  // now the internal
960  for ( UInt i = 0; i < mesh.storedPoints(); ++i )
961  if (!mesh.point (i).boundary() && !isDefinedPointMarker[i])
962  {
963  mesh.point (i).setMarkerID (mesh.markerID() );
964  }
965  UInt counter ( 0 );
966 
967  if ( verbose )
968  {
969  logStream << "**** NEW POINT MARKER MAP **************" << std::endl;
970  logStream << " Point ID -> New Marker\tPoint ID -> New Marker\tPoint ID -> New Marker" << std::endl;
971  isDefinedPointMarkerIterator = isDefinedPointMarker.begin();
972  for ( pointContainerIterator_Type pointContainerIterator = mesh.pointList.begin();
973  pointContainerIterator != mesh.pointList.end(); ++pointContainerIterator )
974  {
975  if ( *isDefinedPointMarkerIterator++ )
976  {
977  logStream << pointContainerIterator->localId() << " -> " <<
978  pointContainerIterator->markerID();
979  logStream << "\t";
980  if ( ++counter % 3 )
981  {
982  logStream << std::endl;
983  }
984  }
985  }
986  logStream << std::endl;
987  }
988 }
989 
990 
991 /*
992  *******************************************************************************
993  FIXING ID AND COUNTERS
994  *******************************************************************************
995  */
996 //! @brief Verifies if a list of mesh entities have the ID properly set.
997 /* More precisely, the localId() must correspond to the position of the entity
998  in the list.
999 
1000  @pre The template argument MeshEntityListType must be a stl
1001  compliant container and its elements must have the method localId().
1002  */
1003 template <typename MeshEntityListType>
1004 bool checkId ( const MeshEntityListType& meshEntityList )
1005 {
1006  typedef typename MeshEntityListType::const_iterator MeshEntityListTypeConstIterator_Type;
1007  bool ok ( true );
1008  UInt counter ( 0 );
1009  for ( MeshEntityListTypeConstIterator_Type meshEntityListIterator = meshEntityList.begin();
1010  meshEntityListIterator != meshEntityList.end() && ok; ++meshEntityListIterator, ++counter )
1011  {
1012  ok = ok && ( meshEntityListIterator->localId() == counter );
1013  }
1014  return ok;
1015 }
1016 
1017 
1018 //! @brief Fixes a a list of mesh entities so that the ID is properly set.
1019 /* @post The localId will correspond to the position of the entity
1020  in the list.
1021 
1022  @pre The template argument MeshEntityListType must be a stl
1023  compliant container and its elements must have the method setLocalId().
1024  */
1025 template <typename MeshEntityListType>
1026 void fixId ( MeshEntityListType& meshEntityList )
1027 {
1028  UInt counter ( 0 );
1029  typedef typename MeshEntityListType::iterator Iter;
1030  for ( Iter meshEntityListIterator = meshEntityList.begin();
1031  meshEntityListIterator != meshEntityList.end(); ++meshEntityListIterator )
1032  {
1033  meshEntityListIterator->setLocalId ( counter++ );
1034  }
1035 }
1036 
1037 
1038 /*! @brief Fixes boundary points counter
1039  It fix the boundary points counter by counting
1040  how many points have the boundary flag set.
1041  It also resets the boundary points list.
1042 
1043  @pre It assumes that the points have the boundary flag correctly set
1044  */
1045 template <typename MeshType>
1046 void
1047 setBoundaryPointsCounters ( MeshType& mesh )
1048 {
1049 
1050  UInt boundaryPointCounter ( 0 );
1051  UInt boundaryVertexCounter ( 0 );
1052 
1053  mesh._bPoints.clear();
1054 
1055  for ( UInt kPointId = 0; kPointId < mesh.numVertices(); ++kPointId )
1056  {
1057  if ( mesh.isBoundaryPoint ( kPointId ) )
1058  {
1059  ++boundaryPointCounter;
1060  ++boundaryVertexCounter;
1061  }
1062  }
1063 
1064  for ( UInt kPointId = mesh.numVertices(); kPointId < mesh.storedPoints(); ++kPointId )
1065  {
1066  if ( mesh.isBoundaryPoint ( kPointId ) )
1067  {
1068  ++boundaryPointCounter;
1069  }
1070  }
1071 
1072  mesh.numBVertices() = boundaryVertexCounter;
1073  mesh.setNumBPoints ( boundaryPointCounter );
1074  mesh._bPoints.clear();
1075  mesh._bPoints.reserve ( boundaryPointCounter );
1076 
1077  for ( UInt kPointId = 0; kPointId < mesh.storedPoints(); ++kPointId )
1078  {
1079  if ( mesh.isBoundaryPoint ( kPointId ) )
1080  {
1081  mesh._bPoints.push_back ( &mesh.point ( kPointId ) );
1082  }
1083  }
1084 }
1085 
1086 
1087 /*
1088  *******************************************************************************
1089 BOUNDARY INDICATOR FIXING
1090  *******************************************************************************
1091  */
1092 //! It fixes boundary flag on points laying on boundary faces.
1093 /*!
1094  @param mesh a mesh
1095  @param logStream logging stream
1096  @param errorStream error stream
1097  @param verbose If true you have a verbose output
1098 
1099  @pre mesh point list must exists and boundary face list must have been set properly.
1100  */
1101 template <typename MeshType>
1102 void
1103 fixBoundaryPoints ( MeshType& mesh, std::ostream& logStream = std::cout,
1104  std::ostream& /* errorStream */ = std::cerr, bool verbose = true )
1105 {
1106  verbose = verbose && ( mesh.comm()->MyPID() == 0 );
1107 
1108  ASSERT_PRE ( mesh.numPoints() > 0, "The point list should not be empty" );
1109  ASSERT_PRE ( mesh.numBFaces() > 0,
1110  "The boundary faces list should not be empty" );
1111 
1112  typedef typename MeshType::facetShape_Type faceShape_Type;
1113 
1114  if ( verbose )
1115  {
1116  logStream << "Fixing BPoints" << std::endl;
1117  }
1118  std::vector<bool> boundaryPoints (mesh.numPoints(), false);
1119  // I may have launched the program for a P2 mesh
1120  // yet not all the points are there
1121  UInt numitems;
1122  if (mesh.storedPoints() == mesh.numVertices() )
1123  {
1124  numitems = faceShape_Type::S_numVertices;
1125  }
1126  else
1127  {
1128  numitems = faceShape_Type::S_numPoints;
1129  }
1130 
1131  for ( UInt kFaceId = 0; kFaceId < mesh.numBFaces(); ++kFaceId )
1132  for ( UInt jPointId = 0; jPointId < numitems; ++jPointId )
1133  {
1134  boundaryPoints[mesh.boundaryFacet (kFaceId).point (jPointId).localId()] = true;
1135  }
1136  for (ID kPointId = 0; kPointId < mesh.storedPoints() ; ++kPointId )
1137  if (boundaryPoints[kPointId])
1138  {
1139  mesh.point (kPointId).setFlag (EntityFlags::PHYSICAL_BOUNDARY);
1140  }
1141  else
1142  {
1143  mesh.point (kPointId).unSetFlag (EntityFlags::PHYSICAL_BOUNDARY);
1144  }
1145  // anihilate
1146  boundaryPoints.clear();
1147  std::vector<bool>().swap (boundaryPoints);
1148  // Fix now the number of vertices/points and reset _bpoints list in the mesh
1149  setBoundaryPointsCounters ( mesh );
1150 }
1151 
1152 
1153 
1154 
1155 /*
1156  *******************************************************************************
1157  UTILITIES TO VERIFY/CREATE FACES/EDGES
1158  *******************************************************************************
1159 */
1160 /**
1161  @brief It rearranges the faces stored in the mesh.
1162 
1163  It makes sure that
1164 
1165  -# Faces have the boundary flag correctly set
1166  -# Boundary faces are stored first
1167 
1168  It uses the information given by findBoundaryFaces, so it relies ONLY on the mesh topology
1169 
1170  It works on a mesh where faces have already been found! So it is not
1171  meant to be used for finding the boundary faces. Use the general utility BuildFaces
1172  for that purpose. Its main role, as the name says, is to make sure that faces are well ordered.
1173  It does not verify the consitency of the face-to-adjacentVolume information. Use fixBoundaryFaces for this purpose
1174 
1175  @param[out] mesh a mesh
1176 
1177  @param[out] logStream stream that will receive all information regarding the markers
1178 
1179  @param[out] errorStream stream for error messages
1180 
1181  @param[out] sw A switch that will contain information on what has been done
1182  Possible values are
1183  <ol>
1184  <li>FACES_REORDERED</li>
1185  </ol>
1186 
1187  @param numFaces[out] It returns the number of faces found by the function
1188 
1189  @param numBoundaryFaces[out] It returns the number of boundary faces found by the function
1190 
1191  @param[in] verbose if false nothing is written to logStream
1192 
1193  @param[out] externalFaceContainer. If not NULL it is a pointer to an external map of boundary faces, already
1194  produced by a call to findBoundaryFaces(). This parameter may be used to save a lot of computational work, since
1195  findBoundaryFaces() is rather expensive.
1196 
1197  @pre Mesh must contain the faces, at least the boundary ones
1198  */
1199 
1200 
1201 template <class MeshType>
1202 bool rearrangeFaces ( MeshType& mesh,
1203  std::ostream& logStream,
1204  std::ostream& errorStream,
1205  Switch& sw,
1206  UInt& numFaces,
1207  UInt& numBoundaryFaces,
1208  bool verbose = false,
1209  temporaryFaceContainer_Type* externalFaceContainer = 0 )
1210 {
1211  verbose = verbose && ( mesh.comm()->MyPID() == 0 );
1212  typedef typename MeshType::faces_Type faceContainer_Type;
1213 
1214  UInt point1Id, point2Id, point3Id, point4Id;
1215  BareFace bareFace;
1216  typename faceContainer_Type::iterator faceContainerIterator;
1217  temporaryFaceContainer_Type* boundaryFaceContainerPtr;
1218  temporaryFaceContainer_Type::iterator boundaryFaceContainerIterator;
1219  UInt numInternalFaces;
1220  bool externalContainerIsProvided ( false );
1221 
1222  if ( (externalContainerIsProvided = ( externalFaceContainer != 0 ) ) )
1223  {
1224  boundaryFaceContainerPtr = externalFaceContainer;
1225  numBoundaryFaces = boundaryFaceContainerPtr->size();
1226  }
1227  else
1228  {
1229  boundaryFaceContainerPtr = new temporaryFaceContainer_Type;
1230  numBoundaryFaces = findBoundaryFaces ( mesh, *boundaryFaceContainerPtr, numInternalFaces );
1231  numFaces = numBoundaryFaces + numInternalFaces;
1232  }
1233 
1234 
1235  bool notEnough = mesh.storedFaces() < numBoundaryFaces;
1236 
1237 
1238 
1239  if ( notEnough )
1240  {
1241  errorStream << "WARNING: number of B. Faces stored smaller" << std::endl;
1242  if (verbose)
1243  {
1244  logStream << "WARNING: number of B. Faces stored smaller" << std::endl;
1245  }
1246  errorStream << " than the number of boundaryFaces found and build is not set"
1247  << std::endl;
1248  errorStream << "ABORT condition in rearrangeFaces" << std::endl;
1249  sw.create ( "BFACE_STORED_MISMATCH", true );
1250  return false;
1251  }
1252 
1253  if ( mesh.numBFaces() == 0 )
1254  {
1255  errorStream << "ERROR: Boundary Element counter was not set" << std::endl;
1256  if ( verbose )
1257  {
1258  logStream << "ERROR: Boundary Element counter was not set" << std::endl;
1259  }
1260  errorStream << "I Cannot proceed because the situation is ambiguous"
1261  << std::endl;
1262  errorStream << "Please check and eventually either: (a) call buildFaces()" << std::endl;
1263  errorStream << "or (b) set the correct number of boundaryFaces in the mesh using mesh.numBFaces()" << std::endl;
1264  errorStream << "ABORT" << std::endl;
1265  sw.create ( "BELEMENT_COUNTER_UNSET", true );
1266  return false;
1267  }
1268 
1269  if ( mesh.numBFaces() != numBoundaryFaces )
1270  {
1271  errorStream << "WARNING: Boundary face counter in mesh is set to "
1272  << mesh.numBFaces() << std::endl;
1273  errorStream << " while I have found " << numBoundaryFaces
1274  << " boundary elements in mesh." << std::endl;
1275  errorStream << " Please check... I continue anyway" << std::endl;
1276  sw.create ( "BFACE_COUNTER_MISMATCH", true );
1277  }
1278 
1279 
1280  for ( faceContainerIterator = mesh.faceList.begin(); faceContainerIterator != mesh.faceList.end();
1281  ++faceContainerIterator )
1282  {
1283  point1Id = ( faceContainerIterator->point ( 0 ) ).localId();
1284  point2Id = ( faceContainerIterator->point ( 1 ) ).localId();
1285  point3Id = ( faceContainerIterator->point ( 2 ) ).localId();
1286 
1287  if ( MeshType::facetShape_Type::S_numVertices == 4 )
1288  {
1289  point4Id = ( faceContainerIterator->point ( 3 ) ).localId();
1290  bareFace = ( makeBareFace ( point1Id, point2Id, point3Id, point4Id ) ).first;
1291  }
1292  else
1293  {
1294  bareFace = ( makeBareFace ( point1Id, point2Id, point3Id ) ).first;
1295  }
1296  boundaryFaceContainerIterator = boundaryFaceContainerPtr->find ( bareFace );
1297  if ( boundaryFaceContainerIterator == boundaryFaceContainerPtr->end() )
1298  {
1299  faceContainerIterator->unSetFlag (EntityFlags::PHYSICAL_BOUNDARY);
1300  }
1301  else
1302  {
1303  faceContainerIterator->setFlag (EntityFlags::PHYSICAL_BOUNDARY);
1304  }
1305  }
1306  mesh.faceList.reorderAccordingToFlag (EntityFlags::PHYSICAL_BOUNDARY, &Flag::testOneSet);
1307 
1308  return true;
1309 }
1310 
1311 //! It fixes boundary faces so that they are consistently numbered with volumes.
1312 
1313 /*! An important step for building degrees of freedom on faces. It also
1314  fixes other face related data.
1315  It works on a mesh where boundary faces have already been found! So it is not
1316  meant to be used for finding the boundary faces. Use the general utility BuildFaces
1317  for that purpose. Its main role, as the name says, is to fix a partially broken mesh.
1318  In particular, it assures that the boundary faces are correctly set w.r.t. the adjacent volumes
1319 
1320 
1321  @param[out] mesh a mesh
1322 
1323  @param[out] logStream stream that will receive all information regarding the markers
1324 
1325  @param[out] errorStream stream for error messages
1326 
1327  @param[out] sw A switch that will contain information on what has been done
1328  Possible values are
1329  <ol>
1330  <li>NUM_FACES_MISMATCH</li>
1331  <li>FIXED_FACE_COUNTER</li>
1332  <li>BFACE_MISSING</li>
1333  <li>BFACE_STORED_MISMATCH</li>
1334  <li>BFACE_COUNTER_UNSET</li>
1335  <li>BFACE_STORED_MISMATCH</li>
1336  <li>FIXED_MAX_NUM_FACES</li>
1337  </ol>
1338 
1339  @param numFaces[out] It returns the number of faces found by the function
1340 
1341  @param numBoundaryFaces[out] It returns the number of boundary faces found by the function
1342 
1343  @param fixMarker[in] If set to the true value, all faces without a markerFlag set will inherit it from the points.
1344  todo remove this parameter (unused)
1345 
1346  @param[in] verbose if false nothing is written to logStream
1347 
1348  @param[out] externalFaceContainer. If not NULL it is a pointer to an external map of boundary faces, already
1349  produced by a call to findBoundaryFaces(). This parameter may be used to save a lot of computational work, since
1350  findBoundaryFaces() is rather expensive.
1351 
1352  @pre Boundary faces list must be properly set.
1353  @todo The policy to treat missing markers should be passed in the argument, so to allow changes
1354  */
1355 
1356 template <class MeshType>
1357 bool fixBoundaryFaces ( MeshType& mesh,
1358  std::ostream& logStream,
1359  std::ostream& errorStream,
1360  Switch& sw,
1361  UInt& numFaces,
1362  UInt& numBoundaryFaces,
1363  bool /* fixMarker */ = false,
1364  bool verbose = false,
1365  temporaryFaceContainer_Type* externalFaceContainer = 0 )
1366 {
1367  verbose = verbose && ( mesh.comm()->MyPID() == 0 );
1368  typedef typename MeshType::volume_Type volume_Type;
1369  typedef typename MeshType::faces_Type faceContainer_Type;
1370  typedef typename MeshType::face_Type face_Type;
1371 
1372  UInt point1Id, point2Id, point3Id, point4Id;
1373  BareFace bareFace;
1374  volume_Type* volumePtr;
1375  typename faceContainer_Type::iterator faceContainerIterator;
1376  typename MeshType::elementShape_Type volumeShape;
1377  temporaryFaceContainer_Type* boundaryFaceContainerPtr;
1378  temporaryFaceContainer_Type::iterator boundaryFaceContainerIterator;
1379  std::pair<ID, ID> volumeIdToLocalFaceIdPair;
1380  ID jFaceLocalId;
1381  ID volumeId;
1382  UInt numInternalFaces;
1383  bool notfound ( false );
1384  bool externalContainerIsProvided ( false );
1385 
1386  if ( (externalContainerIsProvided = ( externalFaceContainer != 0 ) ) )
1387  {
1388  boundaryFaceContainerPtr = externalFaceContainer;
1389  numBoundaryFaces = boundaryFaceContainerPtr->size();
1390  }
1391  else
1392  {
1393  boundaryFaceContainerPtr = new temporaryFaceContainer_Type;
1394  numBoundaryFaces = findBoundaryFaces ( mesh, *boundaryFaceContainerPtr, numInternalFaces );
1395  numFaces = numBoundaryFaces + numInternalFaces;
1396  }
1397 
1398 
1399  bool notEnough = mesh.storedFaces() < numBoundaryFaces;
1400 
1401 
1402 
1403  if ( notEnough )
1404  {
1405  errorStream << "WARNING: number of B. Faces stored smaller" << std::endl;
1406  errorStream << " than the number of boundaryFaces found and build is not set"
1407  << std::endl;
1408  errorStream << "POSSIBLE ERROR" << std::endl;
1409  sw.create ( "BFACE_STORED_MISMATCH", true );
1410  }
1411 
1412  if ( mesh.numBFaces() == 0 )
1413  {
1414  errorStream << "ERROR: Boundary Element counter was not set" << std::endl;
1415  errorStream << "I Cannot proceed because the situation is ambiguous"
1416  << std::endl;
1417  errorStream << "Please check and eventually either: (a) call buildBoundaryFaces()" << std::endl;
1418  errorStream << "or (b) set the correct number of boundaryFaces in the mesh using mesh.numBFaces()" << std::endl;
1419  errorStream << "ABORT" << std::endl;
1420  sw.create ( "BFACE_COUNTER_UNSET", true );
1421  }
1422 
1423  if ( mesh.numBFaces() != numBoundaryFaces )
1424  {
1425  errorStream << "WARNING: Boundary face counter in mesh is set to "
1426  << mesh.numBFaces() << std::endl;
1427  errorStream << " while I have found " << numBoundaryFaces
1428  << " boundary elements in mesh." << std::endl;
1429  errorStream << " Please check... I continue anyway" << std::endl;
1430  sw.create ( "BFACE_COUNTER_MISMATCH", true );
1431  }
1432 
1433  if ( verbose )
1434  {
1435  logStream << "**** Fixed Marker Flags for Boundary Faces ***" << std::endl;
1436  logStream << " (it only contains those that were fixed because unset !)"
1437  << std::endl;
1438  logStream << "id->marker id->marker id->marker" << std::endl;
1439  }
1440 
1441  UInt counter ( 0 );
1442 
1443  faceContainerIterator = mesh.faceList.begin();
1444  for ( UInt facid = 0; facid < mesh.numBFaces(); ++facid )
1445  {
1446  point1Id = ( faceContainerIterator->point ( 0 ) ).localId();
1447  point2Id = ( faceContainerIterator->point ( 1 ) ).localId();
1448  point3Id = ( faceContainerIterator->point ( 2 ) ).localId();
1449  if ( MeshType::facetShape_Type::S_numVertices == 4 )
1450  {
1451  point4Id = ( faceContainerIterator->point ( 3 ) ).localId();
1452  bareFace = ( makeBareFace ( point1Id, point2Id, point3Id, point4Id ) ).first;
1453  }
1454  else
1455  {
1456  bareFace = ( makeBareFace ( point1Id, point2Id, point3Id ) ).first;
1457  }
1458  boundaryFaceContainerIterator = boundaryFaceContainerPtr->find ( bareFace );
1459  if ( boundaryFaceContainerIterator == boundaryFaceContainerPtr->end() )
1460  {
1461  if (verbose)
1462  {
1463  if ( MeshType::facetShape_Type::S_numVertices == 3 )
1464  {
1465  errorStream << "Face " << point1Id << " " << point2Id << " " << point3Id;
1466  }
1467  else
1468  {
1469  errorStream << "Face " << point1Id << " " << point2Id << " " << point3Id << " " << point4Id;
1470  }
1471  errorStream << " stored as boundary face, it's not!" << std::endl;
1472  }
1473  notfound = true;
1474  }
1475  else
1476  {
1477  volumeIdToLocalFaceIdPair = boundaryFaceContainerIterator->second;
1478  volumeId = volumeIdToLocalFaceIdPair.first; // Element ID
1479  volumePtr = &mesh.volume ( volumeId ); // Element
1480  jFaceLocalId = volumeIdToLocalFaceIdPair.second; // The local ID of face on element
1481  // Reset face point definition to be consistent with face.
1482  for ( UInt kPointId = 0; kPointId < face_Type::S_numPoints; ++kPointId )
1483  {
1484  faceContainerIterator->setPoint ( kPointId, volumePtr->point ( volumeShape.faceToPoint ( jFaceLocalId, kPointId ) ) );
1485  }
1486  // Correct extra info
1487  faceContainerIterator->firstAdjacentElementIdentity() = volumeId;
1488  faceContainerIterator->firstAdjacentElementPosition() = jFaceLocalId;
1489  faceContainerIterator->secondAdjacentElementIdentity() = NotAnId;
1490  faceContainerIterator->secondAdjacentElementPosition() = NotAnId;
1491 
1492  if ( faceContainerIterator->isMarkerUnset() )
1493  {
1494  inheritPointsWeakerMarker ( *faceContainerIterator );
1495  if ( verbose )
1496  {
1497  logStream << faceContainerIterator->localId() << " -> " <<
1498  faceContainerIterator->markerID();
1499  logStream << " ";
1500  if ( ++counter % 3 == 0 )
1501  {
1502  logStream << std::endl;
1503  }
1504  }
1505  }
1506  // Take out face from temporary container
1507  boundaryFaceContainerPtr->erase ( boundaryFaceContainerIterator );
1508  }
1509  ++faceContainerIterator;
1510  }
1511 
1512  if ( !externalContainerIsProvided )
1513  {
1514  delete boundaryFaceContainerPtr;
1515  }
1516 
1517  if ( notfound )
1518  {
1519  errorStream << "WARNING: At least one boundary face has not been found on the list stored in MeshType\n";
1520  sw.create ( "BFACE_MISSING", true );
1521  }
1522 
1523  if ( verbose )
1524  {
1525  logStream << std::endl << " ***** END OF LIST ****" << std::endl;
1526  }
1527 
1528  // Here I calculate the number of faces,
1529 
1530  if ( mesh.numFaces() != numFaces )
1531  {
1532  errorStream << "WARNING: faces counter in mesh should be " << numFaces
1533  << std::endl;
1534  errorStream << " (boundaryFaceContainerPtr->size()+numInternalFaces)" << std::endl;
1535  errorStream << " it is instead " << mesh.numFaces() << std::endl;
1536  sw.create ( "NUM_FACES_MISMATCH", true );
1537  }
1538  mesh.setLinkSwitch ( std::string ( "HAS_BOUNDARY_FACETS" ) );
1539 
1540  return true;
1541 }
1542 
1543 
1544 
1545 //! Builds faces
1546 /*! This is a major function.
1547  It may be used to build or partially build faces. So it may operate also on a mesh where
1548  not all boundary faces are set.
1549  Function may alternatively be used to build the compulsory boundary
1550  faces, all the mesh faces, or just add to an existing list of just boundary
1551  faces the internal ones. It will not destroy the basic info (marker id, etc) contained in the
1552  faces list already stored in the meash. So if you want to build everything from scratch you need
1553  to clear it first. It (re)build the adjacent volume info, sets the boundary flags and ensures that
1554  boundary faces are stored first.
1555 
1556 
1557  @param mesh A mesh
1558 
1559  @param logStream Log stream for information on the newly created markers
1560 
1561  @param errorStream Error stream
1562 
1563  @param numBoundaryFaces It returns the number of boundary faces
1564 
1565  @param numInternalFaces It returns the number of internal faces (only if externalFaceContainer is not provided!)
1566 
1567  @param buildBoundaryFaces if true the function builds boundary faces
1568 
1569  @param buildInternalFaces if true the function builds internal faces
1570 
1571  @param verbose If true markerFlags info is written on logStream.
1572 
1573  @param externalFaceContainer. If not NULL it is a pointer to an external map of boundary faces, already
1574  produced by a call to findBoundaryFaces(). This parameter may be used to save a lot of computational work, since
1575  findBoundaryFaces() is rather expensive.
1576 
1577  @pre If buildInternalFaces=true and buildBoundaryFaces=false the mesh must contain a proper list
1578  of boundary faces
1579 
1580  @note By setting buildInternalFaces=true and buildBoundaryFaces=true the function just fixes the counters
1581  with the number of faces in the mesh
1582 
1583  @return true if successful
1584  */
1585 
1586 #ifndef TWODIM
1587 template <class MeshType>
1588 bool buildFaces ( MeshType& mesh,
1589  std::ostream& logStream,
1590  std::ostream& errorStream,
1591  UInt& numBoundaryFaces,
1592  UInt& numInternalFaces,
1593  bool buildBoundaryFaces = true,
1594  bool buildInternalFaces = false,
1595  bool verbose = false,
1596  temporaryFaceContainer_Type* externalFaceContainer = 0 )
1597 {
1598  verbose = verbose && ( mesh.comm()->MyPID() == 0 );
1599  UInt point1Id, point2Id, point3Id, point4Id;
1600  typename MeshType::elementShape_Type volumeShape;
1601  typedef typename MeshType::volumes_Type volumeContainer_Type;
1602  typedef typename MeshType::volume_Type volume_Type;
1603  typedef typename MeshType::face_Type face_Type;
1604  volume_Type* volumePtr;
1605  temporaryFaceContainer_Type* boundaryFaceContainerPtr;
1606  temporaryFaceContainer_Type::iterator boundaryFaceContainerIterator;
1607  bool externalContainerIsProvided ( false );
1608 
1609  std::pair<ID, ID> volumeIdToLocalFaceIdPair;
1610  ID jFaceLocalId, newFaceId;
1611  ID volumeId;
1612  std::map<BareFace, ID> existingFacesMap;
1613  std::map<BareFace, ID>::iterator existingFacesMap_It;
1614  std::pair<std::map<BareFace, ID>::iterator, bool> existingFacesMap_insert;
1615  bool faceExists (false);
1616  // Handle boundary face container
1617  if ( (externalContainerIsProvided = ( externalFaceContainer != 0 ) ) )
1618  {
1619  boundaryFaceContainerPtr = externalFaceContainer;
1620  numBoundaryFaces = boundaryFaceContainerPtr->size();
1621  }
1622  else
1623  {
1624  boundaryFaceContainerPtr = new temporaryFaceContainer_Type;
1625  numBoundaryFaces = findBoundaryFaces ( mesh, *boundaryFaceContainerPtr, numInternalFaces );
1626  }
1627  // Maybe we have already faces stored, save them!
1628  for ( UInt jFaceId = 0; jFaceId < mesh.faceList.size(); ++jFaceId )
1629  {
1630  point1Id = ( mesh.faceList[ jFaceId ].point ( 0 ) ).localId();
1631  point2Id = ( mesh.faceList[ jFaceId ].point ( 1 ) ).localId();
1632  point3Id = ( mesh.faceList[ jFaceId ].point ( 2 ) ).localId();
1633  if ( MeshType::facetShape_Type::S_numVertices == 4 )
1634  {
1635  point4Id = ( mesh.faceList[ jFaceId ].point ( 3 ) ).localId();
1636  existingFacesMap_insert = existingFacesMap.insert (
1637  std::make_pair ( makeBareFace ( point1Id, point2Id, point3Id, point4Id).first, jFaceId )
1638  );
1639 
1640  }
1641  else
1642  {
1643  existingFacesMap_insert = existingFacesMap.insert (
1644  std::make_pair ( makeBareFace ( point1Id, point2Id, point3Id).first, jFaceId )
1645  );
1646  }
1647  if (! existingFacesMap_insert.second)
1648  {
1649  errorStream << "ERROR in BuildFaces. Mesh stores two identical faces" << std::endl;
1650  if ( !externalContainerIsProvided )
1651  {
1652  delete boundaryFaceContainerPtr;
1653  }
1654  return false;
1655  }
1656  }
1657 
1658 
1659  if ( buildBoundaryFaces )
1660  {
1661  mesh.setNumBFaces ( numBoundaryFaces );
1662  }
1663  if ( !buildInternalFaces )
1664  {
1665  mesh.setMaxNumFaces ( std::max (numBoundaryFaces, static_cast<UInt> (mesh.faceList.size() ) ), false );
1666  mesh.setNumFaces ( numInternalFaces + numBoundaryFaces );
1667  }
1668  else
1669  {
1670  mesh.setMaxNumFaces ( numInternalFaces + numBoundaryFaces, true );
1671  }
1672 
1673  face_Type face;
1674 
1675  if ( buildBoundaryFaces )
1676  {
1677 
1678  if ( verbose )
1679  {
1680  logStream << "**** Marker Flags for Newly Created Boundary Faces ***"
1681  << std::endl;
1682  logStream << "id->marker id->marker id->marker" << std::endl;
1683  }
1684 
1685  for ( boundaryFaceContainerIterator = boundaryFaceContainerPtr->begin();
1686  boundaryFaceContainerIterator != boundaryFaceContainerPtr->end(); ++boundaryFaceContainerIterator )
1687  {
1688  existingFacesMap_It = existingFacesMap.find (boundaryFaceContainerIterator->first);
1689  if (existingFacesMap_It != existingFacesMap.end() )
1690  {
1691  faceExists = true;
1692  face = mesh.faceList[existingFacesMap_It->second];
1693  existingFacesMap.erase (existingFacesMap_It);
1694  }
1695  else
1696  {
1697  faceExists = false;
1698  face = face_Type();
1699  face.setId ( mesh.faceList.size() );
1700  }
1701  volumeIdToLocalFaceIdPair = boundaryFaceContainerIterator->second;
1702  volumeId = volumeIdToLocalFaceIdPair.first; // Element ID
1703  volumePtr = &mesh.volume ( volumeId ); // Element
1704  jFaceLocalId = volumeIdToLocalFaceIdPair.second; // The local ID of face on element
1705 
1706  for ( UInt kPointId = 0; kPointId < face_Type::S_numPoints; ++kPointId )
1707  {
1708  face.setPoint ( kPointId, volumePtr->point ( volumeShape.faceToPoint ( jFaceLocalId, kPointId ) ) );
1709  }
1710  // Add extra info
1711  face.firstAdjacentElementIdentity() = volumeId;
1712  face.firstAdjacentElementPosition() = jFaceLocalId;
1713  face.secondAdjacentElementIdentity() = NotAnId;
1714  face.secondAdjacentElementPosition() = NotAnId;
1715  // Get marker value
1716  if ( face.isMarkerUnset() )
1717  {
1718  inheritPointsWeakerMarker ( face );
1719  }
1720  face.setBoundary (true);
1721  if (faceExists)
1722  {
1723  // reset the existing face with new info
1724  newFaceId = face.localId();
1725  mesh.setFace (face, newFaceId);
1726  }
1727  else
1728  {
1729  // The face is new, add it to the mesh
1730  newFaceId = mesh.addFace ( face).localId();
1731  }
1732  if ( verbose )
1733  {
1734  if ( newFaceId % 3 == 0 )
1735  {
1736  logStream << std::endl;
1737  }
1738  logStream << newFaceId << " -> " << face.markerID();
1739  logStream << " ";
1740  }
1741  }
1742  mesh.setLinkSwitch ( std::string ( "HAS_BOUNDARY_FACETS" ) );
1743  if ( ! buildInternalFaces )
1744  {
1745  mesh.unsetLinkSwitch ( std::string ( "HAS_ALL_FACETS" ) );
1746  }
1747  mesh.setLinkSwitch ( std::string ( "FACETS_HAVE_ADIACENCY" ) );
1748  }
1749 
1750  if ( !externalContainerIsProvided )
1751  {
1752  delete boundaryFaceContainerPtr;
1753  }
1754  // All possibly remaining faces are necessarly internal
1755  for (existingFacesMap_It = existingFacesMap.begin(); existingFacesMap_It != existingFacesMap.end();
1756  ++existingFacesMap_It)
1757  {
1758  mesh.faceList[existingFacesMap_It->second].setBoundary (false);
1759  }
1760 
1761  // If there where faces stored originally I need to be sure that bfaces go first!
1762  // I need to do it now because of the tests I do later
1763  if (!existingFacesMap.empty() )
1764  {
1765  mesh.faceList.reorderAccordingToFlag (EntityFlags::PHYSICAL_BOUNDARY, &Flag::testOneSet);
1766  }
1767 
1768  if ( ! buildInternalFaces )
1769  {
1770  // I am done
1771  // Trim BFaces, memory does not come for free!
1772  mesh.faceList.trim();
1773 
1774  return true;
1775  }
1776 
1777 
1778 
1779  if ( !buildBoundaryFaces )
1780  {
1781  if ( mesh.storedFaces() < mesh.numBFaces() )
1782  {
1783  errorStream << "ERROR: mesh has not boundary faces, cannot just create internal ones!!!" << std::endl;
1784  errorStream << "ABORT CONDITION" << std::endl;
1785  return false;
1786  }
1787  }
1788 
1789 
1790  /*
1791  I may get rid of the boundaryFaces container. Unfortunately now I need a more
1792  complex structure, a MeshElementBareHandler, in order to generate the internal
1793  faces id. An alternative would be to use the point data to identify
1794  boundary faces as the ones with all point on the boundary. Yet in this
1795  function we do not want to use a priori information, so that it might
1796  work even if the points boundary flag is not properly set.
1797  */
1798 
1799  MeshElementBareHandler<BareFace> bareFaceHandler;
1800  std::pair<UInt, bool> faceIdToBoolPair;
1801  std::pair<BareFace, bool> _face;
1802  existingFacesMap.clear();
1803  for ( UInt jFaceId = 0; jFaceId < mesh.faceList.size(); ++jFaceId )
1804  {
1805  point1Id = ( mesh.faceList[ jFaceId ].point ( 0 ) ).localId();
1806  point2Id = ( mesh.faceList[ jFaceId ].point ( 1 ) ).localId();
1807  point3Id = ( mesh.faceList[ jFaceId ].point ( 2 ) ).localId();
1808  if ( MeshType::facetShape_Type::S_numVertices == 4 )
1809  {
1810  point4Id = ( mesh.faceList[ jFaceId ].point ( 3 ) ).localId();
1811  _face = makeBareFace ( point1Id, point2Id, point3Id, point4Id );
1812  }
1813  else
1814  {
1815  _face = makeBareFace ( point1Id, point2Id, point3Id );
1816  }
1817  // Store only bfaces by now so if I not find the face is
1818  // certainly an internal face
1819  if (mesh.faceList[ jFaceId ].boundary() )
1820  {
1821  bareFaceHandler.addIfNotThere ( _face.first );
1822  }
1823  else
1824  // I need to track the numbering
1825  {
1826  existingFacesMap.insert (std::make_pair (_face.first, jFaceId) );
1827  }
1828  }
1829  if (bareFaceHandler.howMany() > numBoundaryFaces)
1830  {
1831  errorStream << "ERROR in BuildFaces. Not all boundary faces found, very strange" << std::endl;
1832  errorStream << "ABORT CONDITION" << std::endl;
1833  return false;
1834  }
1835 
1836  for ( typename volumeContainer_Type::iterator volumeContainerIterator = mesh.volumeList.begin();
1837  volumeContainerIterator != mesh.volumeList.end(); ++volumeContainerIterator )
1838  {
1839  volumeId = volumeContainerIterator->localId();
1840  for ( UInt jFaceLocalId = 0; jFaceLocalId < mesh.numLocalFaces(); jFaceLocalId++ )
1841  {
1842  point1Id = volumeShape.faceToPoint ( jFaceLocalId, 0 );
1843  point2Id = volumeShape.faceToPoint ( jFaceLocalId, 1 );
1844  point3Id = volumeShape.faceToPoint ( jFaceLocalId, 2 );
1845  // go to global
1846  point1Id = ( volumeContainerIterator->point ( point1Id ) ).localId();
1847  point2Id = ( volumeContainerIterator->point ( point2Id ) ).localId();
1848  point3Id = ( volumeContainerIterator->point ( point3Id ) ).localId();
1849  if ( MeshType::facetShape_Type::S_numVertices == 4 )
1850  {
1851  point4Id = volumeShape.faceToPoint ( jFaceLocalId, 3 );
1852  point4Id = ( volumeContainerIterator->point ( point4Id ) ).localId();
1853  _face = makeBareFace ( point1Id, point2Id, point3Id, point4Id );
1854  }
1855  else
1856  {
1857  _face = makeBareFace ( point1Id, point2Id, point3Id );
1858  }
1859  faceIdToBoolPair = bareFaceHandler.addIfNotThere ( _face.first );
1860  if ( faceIdToBoolPair.second )
1861  {
1862  // a new face It must be internal.
1863  existingFacesMap_It = existingFacesMap.find (_face.first);
1864  if ( existingFacesMap_It != existingFacesMap.end() )
1865  {
1866  faceExists = true;
1867  face = mesh.faceList[existingFacesMap_It->second];
1868  }
1869  else
1870  {
1871  faceExists = false;
1872  face = face_Type();
1873  face.setId ( mesh.faceList.size() );
1874  }
1875 
1876  for ( UInt kPointId = 0; kPointId < face_Type::S_numPoints; ++kPointId )
1877  {
1878  face.setPoint ( kPointId, volumeContainerIterator->point ( volumeShape.faceToPoint ( jFaceLocalId, kPointId ) ) );
1879  }
1880  face.firstAdjacentElementIdentity() = volumeId;
1881  face.firstAdjacentElementPosition() = jFaceLocalId;
1882  // Marker is unset
1883  if (!faceExists)
1884  {
1885  face.setMarkerID (face.nullMarkerID() );
1886  }
1887  face.setBoundary (false);
1888  if (faceExists)
1889  {
1890  mesh.setFace (face, face.localId() );
1891  // Add it so we can recover the numbering later on!
1892  existingFacesMap.insert ( std::make_pair (_face.first, face.localId() ) );
1893  }
1894  else
1895  {
1896  mesh.addFace ( face);
1897  // Add it so we can recover the numbering
1898  existingFacesMap.insert ( std::make_pair (_face.first, mesh.lastFace().localId() ) );
1899  }
1900  }
1901  else
1902  {
1903  if ( faceIdToBoolPair.first > numBoundaryFaces ) // internal
1904  {
1905  existingFacesMap_It = existingFacesMap.find (_face.first);
1906  mesh.faceList ( existingFacesMap_It->second).secondAdjacentElementIdentity() = volumeId;
1907  mesh.faceList ( existingFacesMap_It->second).secondAdjacentElementPosition() = jFaceLocalId;
1908  }
1909  }
1910  }
1911  }
1912  mesh.setLinkSwitch ( std::string ( "HAS_ALL_FACETS" ) );
1913  return true;
1914 }
1915 #endif
1916 
1917 
1918 //! It builds edges.
1919 /*!
1920  This function may alternatively be used to build the boundary edges,
1921  all the mesh edges, or just add the internal edges to an existing list of
1922  just boundary edges.
1923 
1924  @param mesh A mesh
1925 
1926  @param logStream Log stream for information on the newly created markers for boundary edges
1927 
1928  @param errorStream Error stream
1929 
1930  @param numBoundaryEdgesFound Returns the number of boundary edges
1931 
1932  @param numInternalEdgesFound Returns the number of internal edges
1933 
1934  @param buildBoundaryEdges if true the function builds boundary edges
1935 
1936  @param buildInternalEdges if true the function builds internal edges
1937 
1938  @param verbose. If true markerFlags info is written on logStream.
1939 
1940  @param externalEdgeContainer. If not NULL it is a pointer to an external map of bondary edges, already
1941  produced by a call to findBoundaryEdges(). This parameter may be used to save al lot of computational work, since
1942  findBoundaryEdges() is rather expensive.
1943 
1944  @return true if successful
1945 
1946  @pre If buildInternalEdges=true and buildBoundaryEdges=false the mesh must contain a proper list
1947  of boundary edges
1948 
1949  @pre The mesh must contain a proper list of boundary faces
1950 
1951  @note By setting buildInternalEdges=true and buildBoundaryEdges=true the function just fixes the counters
1952  with the number of edges in the mesh
1953  */
1954 
1955 template <typename MeshType>
1956 bool buildEdges ( MeshType& mesh,
1957  std::ostream& logStream,
1958  std::ostream& errorStream,
1959  UInt& numBoundaryEdgesFound,
1960  UInt& numInternalEdgesFound,
1961  bool buildBoundaryEdges = true,
1962  bool buildInternalEdges = false,
1963  bool verbose = false,
1964  temporaryEdgeContainer_Type* externalEdgeContainer = 0 )
1965 {
1966  verbose = verbose && ( mesh.comm()->MyPID() == 0 );
1967  typedef typename MeshType::volume_Type volume_Type;
1968  typedef typename MeshType::elementShape_Type volumeShape_Type;
1969  typedef typename MeshType::edge_Type edge_Type;
1970  typedef typename MeshType::facetShape_Type faceShape_Type;
1971  typedef typename MeshType::edges_Type::iterator Edges_Iterator;
1972  typename MeshType::face_Type* facePtr;
1973 
1974 
1975  std::map<BareEdge, ID> existingEdges;
1976  typedef std::map<BareEdge, ID>::iterator ExistingEdges_Iterator;
1977  ExistingEdges_Iterator existingEdges_It;
1978  bool edgeExists (false);
1979 
1980  temporaryEdgeContainer_Type* temporaryEdgeContainer;
1981  temporaryEdgeContainer_Type edgeContainer;
1982  std::pair<ID, ID> faceIdToLocalEdgeIdPair;
1983  ID jEdgeLocalId, newEdgeId;
1984  ID faceId;
1985  BareEdge bareEdge;
1986 
1987  bool externalContainerIsProvided ( false );
1988 
1989 
1990  if ( (externalContainerIsProvided = ( externalEdgeContainer != 0 ) ) )
1991  {
1992  temporaryEdgeContainer = externalEdgeContainer;
1993  numBoundaryEdgesFound = temporaryEdgeContainer->size();
1994  }
1995  else
1996  {
1997  temporaryEdgeContainer = new temporaryEdgeContainer_Type;
1998  numBoundaryEdgesFound = findBoundaryEdges ( mesh, *temporaryEdgeContainer );
1999  }
2000 
2001  numInternalEdgesFound = findInternalEdges ( mesh, *temporaryEdgeContainer, edgeContainer );
2002  // free some memory if not needed!
2003  // Dump exisitng edges
2004  ID point1Id;
2005  ID point2Id;
2006  for (Edges_Iterator it = mesh.edgeList.begin(); it < mesh.edgeList.end(); ++it)
2007  {
2008  point1Id = it->point (0).localId();
2009  point2Id = it->point (1).localId();
2010  existingEdges.insert (std::make_pair ( makeBareEdge ( point1Id, point2Id ).first, it->localId() ) );
2011  }
2012 
2013 
2014  if ( !buildBoundaryEdges && buildInternalEdges )
2015  {
2016  if ( mesh.storedEdges() < numBoundaryEdgesFound )
2017  {
2018  errorStream << "ERROR in buildEdges(): mesh does not contain boundary edges" << std::endl;
2019  errorStream << " I need to set buildBoundaryEdges=true" << std::endl;
2020  errorStream << " ABORT CONDITION" << std::endl;
2021  return false;
2022  }
2023  else if ( mesh.storedEdges() > numBoundaryEdgesFound )
2024  {
2025  mesh.edgeList.resize ( numBoundaryEdgesFound );
2026  }
2027  }
2028  mesh.setNumBEdges ( numBoundaryEdgesFound );
2029  mesh.setNumEdges ( numBoundaryEdgesFound + numInternalEdgesFound );
2030 
2031  if ( buildBoundaryEdges && ! buildInternalEdges )
2032  {
2033  mesh.setMaxNumEdges ( numBoundaryEdgesFound, false );
2034  }
2035  if ( buildInternalEdges )
2036  {
2037  mesh.setMaxNumEdges ( numBoundaryEdgesFound + numInternalEdgesFound, true );
2038  }
2039 
2040  if (verbose)
2041  {
2042  errorStream << "Building edges" << std::endl;
2043  }
2044 
2045  edge_Type edge;
2046 
2047  if ( buildBoundaryEdges )
2048  {
2049 
2050  if ( verbose )
2051  {
2052  logStream << "**** Marker Flags for Newly Created Boundary Edges ***"
2053  << std::endl;
2054  logStream << "Edgeid->marker" << std::endl;
2055  }
2056 
2057  // First boundary.
2058  for ( temporaryEdgeContainer_Type::iterator edgeContainerIterator = temporaryEdgeContainer->begin();
2059  edgeContainerIterator != temporaryEdgeContainer->end(); ++edgeContainerIterator )
2060  {
2061  faceIdToLocalEdgeIdPair = edgeContainerIterator->second;
2062  faceId = faceIdToLocalEdgeIdPair.first; // Face ID
2063  facePtr = &mesh.face ( faceId ); // Face
2064  jEdgeLocalId = faceIdToLocalEdgeIdPair.second; // The local ID of edge on face
2065  point1Id = facePtr->point ( faceShape_Type::edgeToPoint ( jEdgeLocalId, 0) ).localId();
2066  point2Id = facePtr->point ( faceShape_Type::edgeToPoint ( jEdgeLocalId, 1) ).localId();
2067  existingEdges_It = existingEdges.find ( ( makeBareEdge ( point1Id, point2Id ) ).first);
2068  if (existingEdges_It != existingEdges.end() )
2069  {
2070  edge = mesh.edge (existingEdges_It->second);
2071  edgeExists = true;
2072 
2073  }
2074  else
2075  {
2076  edge = edge_Type();
2077  edge.setId ( mesh.edgeList.size() );
2078  edgeExists = false;
2079  }
2080  for ( UInt kPointId = 0; kPointId < edge_Type::S_numPoints; ++kPointId )
2081  {
2082  edge.setPoint ( kPointId, facePtr->point ( faceShape_Type::edgeToPoint ( jEdgeLocalId, kPointId ) ) );
2083  }
2084 
2085  // Get marker value inheriting from points if necessary
2086  if ( edge.isMarkerUnset() )
2087  {
2088  inheritPointsWeakerMarker ( edge );
2089  }
2090  edge.setBoundary (true);
2091  if (edgeExists)
2092  {
2093  newEdgeId = edge.localId();
2094  mesh.setEdge (edge, newEdgeId);
2095  }
2096  else
2097  {
2098  newEdgeId = mesh.addEdge ( edge).localId();
2099  }
2100 
2101  if ( verbose )
2102  {
2103  if ( newEdgeId % 6 == 0 )
2104  {
2105  logStream << std::endl;
2106  }
2107  logStream << newEdgeId << " -> " << edge.markerID();
2108  logStream << " ";
2109  }
2110  }
2111 
2112  if ( verbose )
2113  logStream << std::endl << " ***** END OF LIST OF BOUNDARY EDGES ****"
2114  << std::endl;
2115 
2116  mesh.setLinkSwitch ( std::string ( "HAS_BOUNDARY_RIDGES" ) );
2117  }
2118 
2119  if ( !externalContainerIsProvided )
2120  {
2121  delete temporaryEdgeContainer;
2122  }
2123 
2124  if ( !buildInternalEdges )
2125  {
2126  mesh.unsetLinkSwitch ( std::string ( "HAS_ALL_RIDGES" ) );
2127  return true;
2128  }
2129 
2130 
2131 
2132  // Now internal edges
2133  // free some memory
2134  volume_Type* volumePtr;
2135  for ( temporaryEdgeContainer_Type::iterator edgeContainerIterator = edgeContainer.begin();
2136  edgeContainerIterator != edgeContainer.end(); ++edgeContainerIterator )
2137  {
2138  faceIdToLocalEdgeIdPair = edgeContainerIterator->second;
2139  faceId = faceIdToLocalEdgeIdPair.first; // Volume ID
2140  volumePtr = &mesh.volume ( faceId ); // Volume that generated the edge
2141  jEdgeLocalId = faceIdToLocalEdgeIdPair.second; // The local ID of edge on volume
2142  point1Id = volumePtr->point ( volumeShape_Type::edgeToPoint ( jEdgeLocalId, 0) ).localId();
2143  point2Id = volumePtr->point ( volumeShape_Type::edgeToPoint ( jEdgeLocalId, 1) ).localId();
2144  existingEdges_It = existingEdges.find ( ( makeBareEdge ( point1Id, point2Id ) ).first);
2145  if (existingEdges_It != existingEdges.end() )
2146  {
2147  edge = mesh.edge (existingEdges_It->second);
2148  edgeExists = true;
2149 
2150  }
2151  else
2152  {
2153  edge = edge_Type();
2154  edge.setId ( mesh.edgeList.size() );
2155  edgeExists = false;
2156  }
2157  for ( UInt kPointId = 0; kPointId < edge_Type::S_numPoints; ++kPointId )
2158  {
2159  edge.setPoint ( kPointId, volumePtr->point ( volumeShape_Type::edgeToPoint ( jEdgeLocalId, kPointId ) ) );
2160  }
2161 
2162  edge.setMarkerID (edge.nullMarkerID() ); // Set marker to null
2163  edge.setBoundary (false);
2164  if (edgeExists)
2165  {
2166  mesh.setEdge (edge, edge.localId() );
2167  }
2168  else
2169  {
2170  mesh.addEdge ( edge);
2171  }
2172  }
2173 
2174  mesh.setLinkSwitch ( std::string ( "HAS_ALL_RIDGES" ) );
2175 
2176  return true;
2177 }
2178 
2179 
2180 /*
2181  *******************************************************************************
2182  UTILITIES TO TRANSFORM A MESH
2183  *******************************************************************************
2184  */
2185 //! It builds a P2 mesh from P1 data.
2186 /*!
2187  @author L.Formaggia.
2188  @version Version 1.0
2189  @pre All compulsory structures in mesh must have been already set: volumes and boundary faces.
2190  @pre Points list MUST have been dimensioned correctly!!!
2191  @note the function takes advantage of the fact that vertex are stored first
2192  @param mesh[out] A mesh
2193  @param logStream[out] Log stream for information on the newly created markers for boundary edges
2194  */
2195 template <typename MeshType>
2196 void
2197 p2MeshFromP1Data ( MeshType& mesh, std::ostream& logStream = std::cout )
2198 {
2199  bool verbose ( mesh.comm()->MyPID() == 0 );
2200 
2201  typedef typename MeshType::elementShape_Type GeoShape;
2202  typedef typename MeshType::facetShape_Type GeoBShape;
2203  ASSERT_PRE ( GeoShape::S_numPoints > 4, "p2MeshFromP1Data ERROR: we need a P2 mesh" );
2204 
2205  if ( verbose ) logStream << "Building P2 mesh points and connectivities from P1 data"
2206  << std::endl;
2207 
2208 
2209  typename MeshType::point_Type* pointPtr = 0;
2210  typename MeshType::edge_Type* edgePtr = 0;
2211  typename MeshType::volume_Type* elementPtr = 0;
2212  typename MeshType::face_Type* facePtr = 0;
2213 
2214  MeshElementBareHandler<BareEdge> bareEdgeHandler;
2215  std::pair<UInt, bool> edgeIdToBoolPair;
2216  UInt point1Id, point2Id, edgeId;
2217  std::pair<BareEdge, bool> bareEdgeToBoolPair;
2218  typename MeshType::elementShape_Type elementShape;
2219 
2220  if ( verbose )
2221  {
2222  logStream << "Processing " << mesh.storedEdges() << " P1 Edges" << std::endl;
2223  }
2224  UInt numBoundaryEdges = mesh.numBEdges();
2225  for ( UInt jEdgeId = 0; jEdgeId < mesh.storedEdges(); ++jEdgeId )
2226  {
2227  edgePtr = & mesh.edge ( jEdgeId );
2228  point1Id = ( edgePtr->point ( 0 ) ).localId();
2229  point2Id = ( edgePtr->point ( 1 ) ).localId();
2230  pointPtr = & mesh.addPoint ( jEdgeId < numBoundaryEdges, false ); // true for boundary points
2231  pointPtr->setId ( mesh.pointList.size() - 1 );
2232  pointPtr->x() = ( ( edgePtr->point ( 0 ) ).x() +
2233  ( edgePtr->point ( 1 ) ).x() ) * .5;
2234  pointPtr->y() = ( ( edgePtr->point ( 0 ) ).y() +
2235  ( edgePtr->point ( 1 ) ).y() ) * .5;
2236  pointPtr->z() = ( ( edgePtr->point ( 0 ) ).z() +
2237  ( edgePtr->point ( 1 ) ).z() ) * .5;
2238 
2239  /*
2240  If we have set a marker for the boundary edge, that marker is
2241  inherited by the new created point. Otherwise the edge (and the new
2242  created point) gets the WORST marker among the two end Vertices
2243  */
2244  if ( edgePtr->isMarkerUnset() )
2245  {
2246  inheritPointsWeakerMarker ( *edgePtr );
2247  }
2248  pointPtr->setMarkerID ( edgePtr->markerID() );
2249  // todo check that the localId() of the new point is correctly set
2250  edgePtr->setPoint ( 3, pointPtr ); //use overloaded version that takes a pointer
2251  bareEdgeToBoolPair = makeBareEdge ( point1Id, point2Id );
2252  edgeIdToBoolPair = bareEdgeHandler.addIfNotThere ( bareEdgeToBoolPair.first, pointPtr->localId() );
2253  }
2254  // Now the other edges, of which I do NOT build the global stuff
2255  // (I would need to check the switch but I will do that part later on)
2256  if ( GeoShape::S_nDimensions == 3 )
2257  {
2258  UInt numBoundaryFaces = mesh.numBFaces();
2259 
2260  if ( verbose ) logStream << "Processing " << mesh.storedFaces() << " Face Edges"
2261  << std::endl;
2262  for ( UInt kFaceId = 0; kFaceId < mesh.storedFaces(); ++kFaceId )
2263  {
2264  facePtr = &mesh.face ( kFaceId );
2265  for ( UInt jEdgeLocalId = 0; jEdgeLocalId < mesh.numLocalEdgesOfFace(); jEdgeLocalId++ )
2266  {
2267  point1Id = GeoBShape::edgeToPoint ( jEdgeLocalId, 0 );
2268  point2Id = GeoBShape::edgeToPoint ( jEdgeLocalId, 1 );
2269  point1Id = ( facePtr->point ( point1Id ) ).localId();
2270  point2Id = ( facePtr->point ( point2Id ) ).localId();
2271  bareEdgeToBoolPair = makeBareEdge ( point1Id, point2Id );
2272  edgeId = bareEdgeHandler.id ( bareEdgeToBoolPair.first );
2273  if ( edgeId != NotAnId )
2274  {
2275  pointPtr = &mesh.point ( edgeId );
2276  }
2277  else
2278  {
2279  // new edge -> new Point
2280  pointPtr = &mesh.addPoint ( kFaceId < numBoundaryFaces, false ); // true for boundary points
2281  edgeIdToBoolPair = bareEdgeHandler.addIfNotThere ( bareEdgeToBoolPair.first, pointPtr->localId() );
2282  pointPtr->setId ( mesh.pointList.size() - 1 );
2283  pointPtr->x() = ( mesh.point ( point1Id ).x() +
2284  mesh.point ( point2Id ).x() ) * .5;
2285  pointPtr->y() = ( mesh.point ( point1Id ).y() +
2286  mesh.point ( point2Id ).y() ) * .5;
2287  pointPtr->z() = ( mesh.point ( point1Id ).z() +
2288  mesh.point ( point2Id ).z() ) * .5;
2289  // If we have set a marker for the face, that marker is
2290  // inherited by the new created point
2291  pointPtr->setMarkerID ( facePtr->markerID() );
2292  }
2293  facePtr->setPoint ( GeoBShape::S_numVertices + jEdgeLocalId, pointPtr );
2294  }
2295  }
2296  }
2297 
2298  if ( verbose ) logStream << "Processing " << mesh.numElements() << " Mesh Elements"
2299  << std::endl;
2300  UInt nev = GeoShape::S_numVertices;
2301  for ( UInt kElementId = 0; kElementId < mesh.numElements(); ++kElementId )
2302  {
2303  elementPtr = &mesh.element ( kElementId );
2304  for ( UInt jEdgeLocalId = 0; jEdgeLocalId < mesh.numLocalEdges(); jEdgeLocalId++ )
2305  {
2306  point1Id = elementShape.edgeToPoint ( jEdgeLocalId, 0 );
2307  point2Id = elementShape.edgeToPoint ( jEdgeLocalId, 1 );
2308  point1Id = ( elementPtr->point ( point1Id ) ).localId();
2309  point2Id = ( elementPtr->point ( point2Id ) ).localId();
2310  bareEdgeToBoolPair = makeBareEdge ( point1Id, point2Id );
2311  edgeId = bareEdgeHandler.id ( bareEdgeToBoolPair.first );
2312  if ( edgeId != NotAnId )
2313  {
2314  pointPtr = &mesh.point ( edgeId );
2315  }
2316  else
2317  {
2318  // cannot be on boundary if the mesh is proper!
2319  pointPtr = &mesh.addPoint ( false, false );
2320  edgeIdToBoolPair = bareEdgeHandler.addIfNotThere ( bareEdgeToBoolPair.first, pointPtr->localId() );
2321  pointPtr->setId ( mesh.pointList.size() - 1 );
2322  pointPtr->x() = ( mesh.point ( point1Id ).x() +
2323  mesh.point ( point2Id ).x() ) * .5;
2324  pointPtr->y() = ( mesh.point ( point1Id ).y() +
2325  mesh.point ( point2Id ).y() ) * .5;
2326  pointPtr->z() = ( mesh.point ( point1Id ).z() +
2327  mesh.point ( point2Id ).z() ) * .5;
2328  pointPtr->setMarkerID ( edgePtr->markerID() );
2329  }
2330  elementPtr->setPoint ( nev + jEdgeLocalId, pointPtr );
2331  }
2332  }
2333  /*=============================*/
2334  if ( verbose ) logStream << " ******* Done Construction of P2 Mesh *******"
2335  << std::endl << std::endl;
2336 }
2337 
2338 /*! Fix mesh switches
2339  * Using some heuristics it tries to fix mesh switches
2340  */
2341 
2342 // template<typename MeshType>
2343 // void
2344 // fixSwitches(MeshType ^ mesh, std::ostream & logStream=std::cout, bool verbose=false)
2345 // {
2346 
2347 // logStream<<" ************** FIXING MESH SWITCHES **********************"<<std::endl;
2348 // logStream<<" Mesh switches Status before fixing"<<std::endl;
2349 // mesh.showLinkSwitch(verbose,logStream);
2350 // if (mesh.storedFaces()> mesh.numBFaces()){
2351 // mesh.setLinkSwitch("HAS_ALL_FACES");
2352 // } else{
2353 // mesh.unsetLinkSwitch("HAS_ALL_FACES");
2354 // }
2355 // if (mesh.numBFaces>0){
2356 // mesh.setLinkSwitch("HAS_BOUNDARY_FACES");
2357 // } else{
2358 // mesh.unsetLinkSwitch("HAS_BOUNDARY_FACES");
2359 // }
2360 // if (mesh.storedEdges()> mesh.numBEdges()){
2361 // mesh.setLinkSwitch("HAS_ALL_EDGES");
2362 // } else{
2363 // mesh.unsetLinkSwitch("HAS_ALL_EDGES");
2364 // }
2365 // if (mesh.numBEdges()> 0){
2366 // mesh.setLinkSwitch("HAS_BOUNDARY_EDGES");
2367 // } else{
2368 // mesh.unsetLinkSwitch("HAS_BOUNDAY_EDGES");
2369 // }
2370 // if (mesh.storedFaces()>0){
2371 // if(mesh.face(0).firstAdjacentElementIdentity(
2372 // mesh.setLinkSwitch("HAS_BOUNDARY_EDGES");
2373 // } else{
2374 // mesh.unsetLinkSwitch("HAS_BOUNDAY_EDGES");
2375 // }
2376 
2377 /** Class to transform a mesh.
2378  * A class that implements methods to transform a mesh without changing
2379  * mesh connectivities. It has a constructor that takes the mesh to be transformed
2380  * @note The Template RMTYPE is used to compile with IBM AIX compilers
2381  * @author Luca Formaggia
2382  * @date 2 August 2011
2383  */
2384 //
2385 template <typename REGIONMESH, typename RMTYPE = typename REGIONMESH::markerCommon_Type >
2387 {
2388 public:
2389  /** the constructor may take a reference to the mesh to be manipulated */
2390  MeshTransformer (REGIONMESH& m);
2391  /** Move the mesh according to a given displacement.
2392  *
2393  * It moves the mesh from the last position saved with savePoints()
2394  * For backward compatibility, if it is called before without calling
2395  * savePoints(), the first time it is called it will save the current mesh point and then
2396  * apply the movement.
2397  *
2398  * Displacement is a 3*numpoints() VECTOR which stores the x-displacement first,
2399  * then the y-displacements etc.
2400  *
2401  * The VECTOR object must comply with lifeV distributed vector concept EpetraVector
2402  * in particular it must have the methods isGlobalIDPresent(Uint i).
2403  *
2404  * @author Miguel Fernandez
2405  * @date 11/2002
2406  *
2407  * @param disp Displacement vector. In this version it must be an EpetraVector
2408  * @param dim Length of vector disp.
2409  */
2410  template <typename VECTOR>
2411  void moveMesh ( const VECTOR& disp, UInt dim);
2412  /** Transform the mesh. It uses boost::numeric::ublas (3,3) matrices
2413  * scale, rotate and translate to perform the mesh movement
2414  * (operations performed in this order).
2415  * @date 14/09/2009
2416  * @author Cristiano Malossi
2417  * @note - Rotation follows Paraview conventions: first rotate around z-axis,
2418  * then around y-axis and finally around x-axis;
2419  * @note - All the vectors must allow the command: operator[];
2420  * @param scale vector of three components for (x,y,z) scaling of the mesh
2421  * @param rotate vector of three components (radiants) for rotating the mesh
2422  * @param translate vector of three components for (x,y,z) translation the mesh
2423  *
2424  */
2425  template <typename VECTOR>
2426  void transformMesh ( const VECTOR& scale, const VECTOR& rotate, const VECTOR& translate );
2427 
2428  /** Transform the mesh according to a given mapping.
2429  * Transform the mesh according to a given meshMapping(Real& x, Real& y, Real& z).
2430  * @date 12/2010
2431  * @author Mauro Perego
2432  * @param meshMapping function void meshMmapping(Real& x, Real& y, Real& z) which receive
2433  * x, y, z, and transform them according to a certain mapping
2434  */
2435  template <typename function>
2436  void transformMesh ( const function& meshMapping);
2437 
2438  //! Tells if we store old points
2439  /**
2440  * If true than we can interrogate the old point position
2441  */
2442  bool hasOldPoint() const
2443  {
2444  return ! (this->M_pointList.empty() );
2445  }
2446  //! Saves the mesh points
2447  /**
2448  * Useful for algorithms which require to remember the position of the mesh
2449  * before the movement
2450  */
2451  void savePoints();
2452  /** Resets movement. Next step is like the mesh has never moved
2453  */
2455  {
2456  this->M_pointList.clear();
2457  }
2458 
2459  /** Returns the i-th mesh Point before the last movement.
2460 
2461  *
2462  * If the mesh points have not been saved with a previous call to
2463  * savePoints() the method returns the mesh point
2464  *
2465  * @note Avoid extensive use: it is inefficient. use pointListInitial() instead
2466  * @param i Id of the Point.
2467  * @return i-th mesh Point before the last movement.
2468  */
2469  typename REGIONMESH::point_Type const& pointInitial ( ID const i ) const;
2470  /** Returns a constant reference to the list of Points before the last movement.
2471  *
2472  * If the mesh points have not been saved with a previous call to
2473  * savePoints() returns the current mesh Points
2474  *
2475  * @return The list mesh Point before the last movement.
2476  */
2477  typename REGIONMESH::points_Type const& pointListInitial() const;
2478 private:
2479  /** Appropriately sets internal switches
2480  *
2481  * It must be called by any mesh transformation method
2482  * to ensure that the handling of (possibly) stored points
2483  * works;
2484  */
2485  REGIONMESH& M_mesh;
2486  typename REGIONMESH::points_Type M_pointList;
2487 };
2488 /** Mesh statistics.
2489  * Namespace that groups functions which operate on a mesh to extract statistics.
2490  * The functions do not modify mesh content
2491  * @author Luca Formaggia
2492  * @date 3 August 2011
2493  */
2495 {
2496 
2497 /** It holds statistics on mesh size.
2498  * Mesh spacings:
2499  * meshSize.minH Min h
2500  * meshsize.maxH Max h
2501  * meshsize.meanH Average h
2502  */
2503 struct meshSize
2504 {
2508 };
2509 //! Computes mesh sizes
2510 template<typename REGIONMESH>
2511 meshSize computeSize (const REGIONMESH&);
2512 }// namespace MeshStatistics
2513 
2514 // ***** IMPLEMENTATIONS ****
2515 // The Template RMTYPE is used to compile with IBM compilers
2516 template <typename REGIONMESH, typename RMTYPE >
2517 MeshTransformer<REGIONMESH, RMTYPE >::MeshTransformer (REGIONMESH& m) : M_mesh (m), M_pointList() {}
2518 /**
2519  * @todo this method should be changed to make sure not to generate invalid elements
2520  */
2521 template <typename REGIONMESH, typename RMTYPE >
2522 template <typename VECTOR>
2523 void MeshTransformer<REGIONMESH, RMTYPE >::moveMesh ( const VECTOR& disp, UInt dim )
2524 {
2525  // the method must be called with a Repeated vector
2526  if ( disp.mapType() == Unique )
2527  {
2528 #ifdef HAVE_LIFEV_DEBUG
2529  std::cerr << "Info: moveMesh() requires a Repeated vector, a copy of the passed Unique vector will be created.\n"
2530  << "To optimize your code, you should pass a repeated vector to avoid the conversion." << std::endl;
2531 #endif
2532  this->moveMesh ( VECTOR ( disp, Repeated ), dim );
2533  return;
2534  }
2535 
2536  if ( !this->hasOldPoint() )
2537  {
2538  this->savePoints();
2539  }
2540 
2541  typedef typename REGIONMESH::points_Type points_Type;
2542  points_Type& pointList ( M_mesh.pointList );
2543  for ( UInt i = 0; i < M_mesh.pointList.size(); ++i )
2544  {
2545  for ( UInt j = 0; j < nDimensions; ++j )
2546  {
2547  int globalId = pointList[i].id();
2548  ASSERT ( disp.isGlobalIDPresent ( globalId + dim * j ), "global ID missing" );
2549  pointList[ i ].coordinate ( j ) = M_pointList[ i ].coordinate ( j ) + disp[ j * dim + globalId ];
2550  }
2551  }
2552 }
2553 
2554 template<typename REGIONMESH, typename RMTYPE >
2555 void MeshTransformer<REGIONMESH, RMTYPE >::savePoints()
2556 {
2557  if (M_pointList.capacity() < M_mesh.pointList.size() )
2558  {
2559  // Create space and add
2560  M_pointList.clear();
2561  M_pointList.reserve ( M_mesh.numPoints() );
2562  std::copy (M_mesh.pointList.begin(), M_mesh.pointList.end(),
2563  std::back_inserter (M_pointList) );
2564  }
2565  else
2566  {
2567  // Overwrite
2568  std::copy (M_mesh.pointList.begin(), M_mesh.pointList.end(), M_pointList.begin() );
2569  }
2570 }
2571 // The Template RMTYPE is used to compile with IBM compilers
2572 template <typename REGIONMESH, typename RMTYPE >
2573 const typename REGIONMESH::point_Type&
2574 MeshTransformer<REGIONMESH, RMTYPE >::pointInitial ( ID const i ) const
2575 {
2576  ASSERT_BD ( i < M_mesh.pointList.size() );
2577  return M_pointList.empty() ? M_mesh.pointList[i] : this->M_pointList[i];
2578 }
2579 
2580 template <typename REGIONMESH, typename RMTYPE >
2581 const typename REGIONMESH::points_Type&
2582 MeshTransformer<REGIONMESH, RMTYPE >::pointListInitial() const
2583 {
2584  return M_pointList.empty() ? M_mesh.points_Type : M_pointList;
2585 }
2586 // The Template RMTYPE is used to compile with IBM compilers
2587 //! @todo Change using homogeneous coordinates to make it more efficient.
2588 template <typename REGIONMESH, typename RMTYPE >
2589 template <typename VECTOR>
2590 void MeshTransformer<REGIONMESH, RMTYPE >::transformMesh ( const VECTOR& scale, const VECTOR& rotate, const VECTOR& translate )
2591 {
2592  // Make life easier
2593  typename REGIONMESH::points_Type& pointList (M_mesh.pointList);
2594 
2595  //Create the 3 planar rotation matrix and the scale matrix
2596  boost::numeric::ublas::matrix<Real> R (3, 3), R1 (3, 3), R2 (3, 3), R3 (3, 3), S (3, 3);
2597 
2598  R1 (0, 0) = 1.;
2599  R1 (0, 1) = 0.;
2600  R1 (0, 2) = 0.;
2601  R1 (1, 0) = 0.;
2602  R1 (1, 1) = std::cos (rotate[0]);
2603  R1 (1, 2) = -std::sin (rotate[0]);
2604  R1 (2, 0) = 0.;
2605  R1 (2, 1) = std::sin (rotate[0]);
2606  R1 (2, 2) = std::cos (rotate[0]);
2607 
2608  R2 (0, 0) = std::cos (rotate[1]);
2609  R2 (0, 1) = 0.;
2610  R2 (0, 2) = std::sin (rotate[1]);
2611  R2 (1, 0) = 0.;
2612  R2 (1, 1) = 1.;
2613  R2 (1, 2) = 0.;
2614  R2 (2, 0) = -std::sin (rotate[1]);
2615  R2 (2, 1) = 0.;
2616  R2 (2, 2) = std::cos (rotate[1]);
2617 
2618  R3 (0, 0) = std::cos (rotate[2]);
2619  R3 (0, 1) = -std::sin (rotate[2]);
2620  R3 (0, 2) = 0.;
2621  R3 (1, 0) = std::sin (rotate[2]);
2622  R3 (1, 1) = std::cos (rotate[2]);
2623  R3 (1, 2) = 0.;
2624  R3 (2, 0) = 0;
2625  R3 (2, 1) = 0.;
2626  R3 (2, 2) = 1.;
2627 
2628  S (0, 0) = scale[0];
2629  S (0, 1) = 0.;
2630  S (0, 2) = 0.;
2631  S (1, 0) = 0.;
2632  S (1, 1) = scale[1];
2633  S (1, 2) = 0.;
2634  S (2, 0) = 0.;
2635  S (2, 1) = 0.;
2636  S (2, 2) = scale[2];
2637 
2638  //The total rotation is: R = R1*R2*R3 (as in Paraview we rotate first around z, then around y, and finally around x).
2639  //We also post-multiply by S to apply the scale before the rotation.
2640  R = prod ( R3, S );
2641  R = prod ( R2, R );
2642  R = prod ( R1, R );
2643 
2644  //Create the 3D translate vector
2645  boost::numeric::ublas::vector<Real> P (3), T (3);
2646  T (0) = translate[0];
2647  T (1) = translate[1];
2648  T (2) = translate[2];
2649 
2650  //Apply the transformation
2651  for ( UInt i (0); i < pointList.size(); ++i )
2652  {
2653  //P = pointList[ i ].coordinate(); // Try to avoid double copy if possible
2654 
2655  P ( 0 ) = pointList[ i ].coordinate ( 0 );
2656  P ( 1 ) = pointList[ i ].coordinate ( 1 );
2657  P ( 2 ) = pointList[ i ].coordinate ( 2 );
2658 
2659  P = T + prod ( R, P );
2660 
2661  pointList[ i ].coordinate ( 0 ) = P ( 0 );
2662  pointList[ i ].coordinate ( 1 ) = P ( 1 );
2663  pointList[ i ].coordinate ( 2 ) = P ( 2 );
2664  }
2665 }
2666 // The Template RMTYPE is used to compile with IBM compilers
2667 template <typename REGIONMESH, typename RMTYPE >
2668 template <typename function>
2669 void MeshTransformer<REGIONMESH, RMTYPE >::transformMesh ( const function& meshMapping)
2670 {
2671  // Make life easier
2672  typename REGIONMESH::points_Type& pointList (M_mesh.pointList);
2673 
2674  for ( UInt i = 0; i < pointList.size(); ++i )
2675  {
2676  typename REGIONMESH::point_Type& p = pointList[ i ];
2677  meshMapping (p.coordinate (0), p.coordinate (1), p.coordinate (2) );
2678  }
2679 }
2680 
2681 template <typename REGIONMESH>
2682 MeshStatistics::meshSize MeshStatistics::computeSize (REGIONMESH const& mesh)
2683 {
2684  const Real bignumber = std::numeric_limits<Real>::max();
2685  Real MaxH (0), MinH (bignumber), MeanH (0);
2686  Real deltaX (0), deltaY (0), deltaZ (0), sum (0);
2687  typedef typename REGIONMESH::edges_Type edges_Type;
2688  edges_Type const& edgeList (mesh.edgeList);
2689 
2690  ASSERT0 (edgeList.size() > 0, "computeSize requires edges!");
2691 
2692  for (typename edges_Type::const_iterator i = edgeList.begin(); i < edgeList.end() ; ++i )
2693  {
2694  deltaX = i->point ( 1 ).x() - i->point ( 0 ).x();
2695  deltaY = i->point ( 1 ).y() - i->point ( 0 ).y();
2696  deltaZ = i->point ( 1 ).z() - i->point ( 0 ).z();
2697 
2698  deltaX *= deltaX;
2699  deltaY *= deltaY;
2700  deltaZ *= deltaZ;
2701  sum = deltaX + deltaY + deltaZ;
2702  MaxH = std::max ( MaxH, sum);
2703  MinH = std::min ( MinH, sum);
2704  MeanH += sum;
2705  }
2706 
2707  MeshStatistics::meshSize out;
2708  out.minH = std::sqrt ( MinH );
2709  out.meanH = std::sqrt ( MeanH / static_cast<Real> ( edgeList.size() ) );
2710  out.maxH = std::sqrt ( MaxH );
2711  return out;
2712 }
2713 
2714 template <typename RegionMeshType, typename RegionFunctorType>
2715 void assignRegionMarkerID ( RegionMeshType& mesh, const RegionFunctorType& fun )
2716 {
2717 
2718  // Extract the element list.
2719  typename RegionMeshType::elements_Type& elementList = mesh.elementList ();
2720  const UInt elementListSize = elementList.size();
2721 
2722  // Loop on the elements and decide the flag.
2723  for ( UInt i = 0; i < elementListSize; ++i )
2724  {
2725  // Computes the barycentre of the element
2726  Vector3D barycentre;
2727 
2728  for ( UInt k = 0; k < RegionMeshType::element_Type::S_numPoints; k++ )
2729  {
2730  barycentre += elementList[i].point ( k ).coordinates();
2731  }
2732  barycentre /= RegionMeshType::element_Type::S_numPoints;
2733 
2734  // Set the marker Id.
2735  elementList[i].setMarkerID ( fun ( barycentre ) );
2736 
2737  }
2738 
2739 } // assignRegionMarkerID
2740 
2741 } // namespace MeshUtility
2742 
2743 } // namespace LifeV
2744 
2745 #endif /* MESHUTILITY_H */
This is the base class to store basic properties of any mesh entity.
Definition: MeshEntity.hpp:97
mesh_Type::facetShape_Type faceShape_Type
void fixBoundaryPoints(MeshType &mesh, std::ostream &logStream=std::cout, std::ostream &=std::cerr, bool verbose=true)
It fixes boundary flag on points laying on boundary faces.
UInt findFaces(const MeshType &mesh, temporaryFaceContainer_Type &boundaryFaceContainer, UInt &numInternalFaces, temporaryFaceContainer_Type &internalFaces, bool buildAllFaces=false)
Finds mesh faces.
EnquireBEdge(temporaryEdgeContainer_Type const &boundaryEdgeContainer)
Constructor taking a mesh object and an edge container.
EnquireBFace()
Empty Constructor.
void transformMesh(const VECTOR &scale, const VECTOR &rotate, const VECTOR &translate)
Transform the mesh.
UInt findInternalEdges(const MeshType &mesh, const temporaryEdgeContainer_Type &boundaryEdgeContainer, temporaryEdgeContainer_Type &internalEdgeContainer)
Finds internal edges.
The base Face class.
std::map< BareFace, std::pair< ID, ID >, cmpBareItem< BareFace > > temporaryFaceContainer_Type
A locally used structure, not meant for general use.
Definition: MeshUtility.hpp:72
#define ASSERT_BD(X)
Definition: LifeAssert.hpp:114
Class to transform a mesh.
I use standard constructor/destructors.
Definition: Switch.hpp:50
virtual ~GetOnes()
Virtual Destructor.
bool checkId(const MeshEntityListType &meshEntityList)
Verifies if a list of mesh entities have the ID properly set.
Functor to check if a Face is on the boundary.
Definition: MeshUtility.hpp:96
temporaryFaceContainer_Type const * temporaryFaceContainerPtr_Type
REGIONMESH::point_Type const & pointInitial(ID const i) const
Returns the i-th mesh Point before the last movement.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
UInt testDomainTopology(MeshType const &mesh, UInt &numBoundaryEdges)
GetCoordComponent(Int i)
Constructor taking the component.
Definition: MeshUtility.cpp:49
bool buildFaces(MeshType &mesh, std::ostream &logStream, std::ostream &errorStream, UInt &numBoundaryFaces, UInt &numInternalFaces, bool buildBoundaryFaces=true, bool buildInternalFaces=false, bool verbose=false, temporaryFaceContainer_Type *externalFaceContainer=0)
Builds faces.
ID markerID_Type
markerID_Type is the type used to store the geometric entity marker IDs
Definition: Marker.hpp:81
virtual ~EnquireBEdge()
Virtual Destructor.
GetOnes(const GetOnes &)
Copy Constructor.
void updateInverseJacobian(const UInt &iQuadPt)
EnquireBPoint(EnquireBPoint const &enquireBoundaryPoint)
Copy Constructor.
MeshTransformer(REGIONMESH &m)
the constructor may take a reference to the mesh to be manipulated
void create(const char *a, bool status=false)
Definition: Switch.cpp:126
bool testOneSet(flag_Type const &inputFlag, flag_Type const &refFlag)
returns true if at least one flag set in refFlag is set in inputFlag
Definition: LifeV.hpp:216
UInt findBoundaryEdges(const MeshType &mesh, temporaryEdgeContainer_Type &boundaryEdgeContainer)
Finds boundary edges.
EnquireBPoint(mesh_Type &mesh)
Constructor taking a mesh object.
void setBoundaryEdgesMarker(MeshType &mesh, std::ostream &logStream=std::cout, std::ostream &=std::cerr, bool verbose=true)
Sets the marker id for all boundary edges by inheriting them from boundary points.
This functor is used to do some geometry checks.
EnquireBFace(temporaryFaceContainer_Type const &boundaryFaceContainer)
Constructor taking a mesh object and a face Entity.
#define ASSERT_PRE(X, A)
Definition: LifeAssert.hpp:96
The Edge basis class.
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
uint32_type ID
IDs.
Definition: LifeV.hpp:194
mesh_Type::face_Type face_Type
void assignRegionMarkerID(RegionMeshType &mesh, const RegionFunctorType &fun)
void savePoints()
Saves the mesh points.
const flag_Type PHYSICAL_BOUNDARY(0x01)
bool operator()(const MeshEntity &meshEntity) const
The function call operator.
meshSize computeSize(const REGIONMESH &)
Computes mesh sizes.
bool boundary() const
Tells if it is on the boundary.
Definition: MeshEntity.hpp:260
void operator()(Real const &x, Real const &y, Real const &z, Real ret[3]) const
The function call operator.
Definition: MeshUtility.cpp:55
#define ASSERT0(X, A)
Definition: LifeAssert.hpp:71
void setBoundaryFacesMarker(MeshType &mesh, std::ostream &logStream=std::cout, std::ostream &=std::cerr, bool verbose=true)
Sets the marker ID for all boundary faces by inheriting them from boundary points.
REGIONMESH::points_Type M_pointList
bool buildEdges(MeshType &mesh, std::ostream &logStream, std::ostream &errorStream, UInt &numBoundaryEdgesFound, UInt &numInternalEdgesFound, bool buildBoundaryEdges=true, bool buildInternalEdges=false, bool verbose=false, temporaryEdgeContainer_Type *externalEdgeContainer=0)
It builds edges.
markerID_Type inheritPointsWeakerMarker(MeshElementMarkedType &geoElement)
Sets the marker ID of a MeshElementMarked of dimension greater one.
double Real
Generic real data.
Definition: LifeV.hpp:175
REGIONMESH & M_mesh
Appropriately sets internal switches.
UInt findBoundaryFaces(const MeshType &mesh, temporaryFaceContainer_Type &boundaryFaceContainer, UInt &numInternalFaces)
Finds boundary faces.
flag related free functions and functors
Definition: LifeV.hpp:203
temporaryEdgeContainerPtr_Type boundaryEdgeContainerPtr
bool checkIsMarkerSet(const MeshEntityListType &meshEntityList)
Check whether all markers of a the geometry entities stored in a list are set.
void setBoundaryPointsMarker(MeshType &mesh, std::ostream &logStream=std::cout, std::ostream &=std::cerr, bool verbose=false)
It sets the marker ID for Points, by inheriting it from facets.
bool rearrangeFaces(MeshType &mesh, std::ostream &logStream, std::ostream &errorStream, Switch &sw, UInt &numFaces, UInt &numBoundaryFaces, bool verbose=false, temporaryFaceContainer_Type *externalFaceContainer=0)
It rearranges the faces stored in the mesh.
container_Type::const_iterator containerConstIterator_Type
temporaryEdgeContainer_Type const * temporaryEdgeContainerPtr_Type
available bit-flags for different geometric properties
Definition: MeshEntity.hpp:48
EnquireBEdge()
Empty Constructor.
const UInt nDimensions(NDIM)
void p2MeshFromP1Data(MeshType &mesh, std::ostream &logStream=std::cout)
It builds a P2 mesh from P1 data.
GetCoordComponent(const GetCoordComponent &getCoordComponent)
Copy constructor.
temporaryFaceContainerPtr_Type boundaryFaceContainerPtr
virtual ~EnquireBFace()
Virtual Destructor.
REGIONMESH::points_Type const & pointListInitial() const
Returns a constant reference to the list of Points before the last movement.
bool fixBoundaryFaces(MeshType &mesh, std::ostream &logStream, std::ostream &errorStream, Switch &sw, UInt &numFaces, UInt &numBoundaryFaces, bool=false, bool verbose=false, temporaryFaceContainer_Type *externalFaceContainer=0)
It fixes boundary faces so that they are consistently numbered with volumes.
const ID NotAnId
Definition: LifeV.hpp:264
VectorSmall< 3 > Vector3D
void resetMovement()
Resets movement.
EnquireBEdge(EnquireBEdge const &enquireBoundaryEdge)
Copy Constructor.
bool operator()(const face_Type &face) const
The function call operator.
GetOnes()
Empty Constructor.
Assert & error(const char *strMsg=0)
bool operator()(const edge_Type &edge) const
The function call operator.
virtual ~GetCoordComponent()
Virtual Destructor.
markerID_Type inheritPointsStrongerMarker(MeshElementMarkedType &geoElement)
void transformMesh(const function &meshMapping)
Transform the mesh according to a given mapping.
bool hasOldPoint() const
Tells if we store old points.
GetCoordComponent()
Empty Constructor.
Definition: MeshUtility.cpp:46
It holds statistics on mesh size.
void operator()(Real const &x, Real const &y, Real const &z, Real ret[3]) const
The function call operator.
Definition: MeshUtility.cpp:81
virtual ~EnquireBPoint()
Virtual Destructor.
std::map< BareEdge, std::pair< ID, ID >, cmpBareItem< BareEdge > > temporaryEdgeContainer_Type
A locally used structure, not meant for general use.
Definition: MeshUtility.hpp:76
void moveMesh(const VECTOR &disp, UInt dim)
Move the mesh according to a given displacement.
EnquireBPoint()
Empty Constructor.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
void fixId(MeshEntityListType &meshEntityList)
Fixes a a list of mesh entities so that the ID is properly set.
void setBoundaryPointsCounters(MeshType &mesh)
Fixes boundary points counter It fix the boundary points counter by counting how many points have the...
mesh_Type::edge_Type edge_Type