LifeV
MeshPartBuilder.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, 2011, 2012 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 Class that builds a mesh part, after the graph has been partitioned
30 
31  @date 9-11-2012
32  @author Radu Popescu <radu.popescu@epfl.ch>
33 
34  @maintainer Radu Popescu <radu.popescu@epfl.ch>
35 */
36 
37 #ifndef MESH_PART_BUILDER_H
38 #define MESH_PART_BUILDER_H 1
39 
40 #include <boost/shared_ptr.hpp>
41 
42 #include <Epetra_Comm.h>
43 
44 #include<lifev/core/LifeV.hpp>
45 
46 #include <lifev/core/array/GhostHandler.hpp>
47 #include <lifev/core/mesh/GraphCutterBase.hpp>
48 #include <lifev/core/mesh/GraphUtil.hpp>
49 
50 namespace LifeV
51 {
52 
53 using namespace GraphUtil;
54 
55 /*!
56  @brief Class that builds a mesh part, after the graph has been partitioned
57  @author Radu Popescu radu.popescu@epfl.ch
58 
59  This class is used as a component for the MeshPartitionTool class. When an
60  object of class MeshPartBuilder is instantiated it holds pointer to the
61  global uncut mesh.
62 
63  The only public method that this class implements is a run method, which
64  takes a vector of element IDs which corespond to a mesh part and builds
65  a RegionMesh object with this elements.
66 */
67 template<typename MeshType>
69 {
70 public:
71  //! @name Public Types
72  //@{
73  typedef MeshType mesh_Type;
76  typedef struct
77  {
82  } entityPID_Type;
83  //@}
84 
85  //! \name Constructors & Destructors
86  //@{
87 
88  //! Constructor
89  /*!
90  * Constructor which takes a pointer to a RegionMesh object, the uncut
91  * mesh
92  *
93  * \param mesh - shared pointer to the global uncut mesh
94  */
95  MeshPartBuilder (const meshPtr_Type& mesh,
96  const UInt overlap,
97  const commPtr_Type& comm);
98 
99  //! Empty destructor
101  //@}
102 
103  //! \name Public Methods
104  //@{
105  //! Run part builder
106  /*!
107  * This method performs all the steps for the mesh and graph partitioning
108  *
109  * \param meshPart - shared pointer to a RegionMesh object which will
110  * contain the mesh part
111  * \param elementList - shared pointer to a vector of int, representing the
112  * element IDs associated with this mesh part
113  */
114  void run (const meshPtr_Type& meshPart,
115  const idTablePtr_Type& graph,
116  const entityPID_Type& entityPIDList,
117  const UInt partIndex);
118 
119  //! Resets the MeshPartBuilder object to the initial state
120  void reset();
121  //@}
122 
123  //! \name Get Methods
124  //@{
125  const std::map<Int, Int>& globalToLocalElement() const
126  {
127  return M_globalToLocalElement;
128  }
129  //@}
130 
131 private:
132  //! Private Methods
133  //@{
134  //! Construct local mesh
135  /*!
136  Constructs the data structures for the local mesh partition.
137  Updates M_localVertices, M_localRidges, M_localFacets, M_localElements,
138  M_globalToLocalVertex.
139  */
140  void constructLocalMesh (const std::vector<Int>& elementList);
141  //! Construct nodes
142  /*!
143  Adds nodes to the partitioned mesh object. Updates M_nBoundaryVertices,
144  M_meshPartition.
145  */
146  void constructNodes();
147  //! Construct volumes
148  /*!
149  Adds volumes to the partitioned mesh object.
150  Updates M_globalToLocalElement, M_meshPartition.
151  */
152  void constructElements();
153  //! Construct edges
154  /*!
155  Adds edges to the partitioned mesh object. Updates M_nBoundaryRidges,
156  M_meshPartition.
157  */
158  void constructRidges();
159  //! Construct faces
160  /*!
161  Adds faces to the partitioned mesh object. Updates M_nBoundaryFacets,
162  M_meshPartition.
163  */
164  void constructFacets();
165  //! Final setup of local mesh
166  /*!
167  Updates the partitioned mesh object data members after adding the mesh
168  elements (nodes, edges, faces, volumes).
169  Updates M_meshPartition.
170  */
171  void finalSetup();
172  //@}
173 
174  //! Mark entity ownership
175  /*!
176  Mark all owned entities in the partition with EntityFlag::OWNED
177  to properly build map members in DOF::GlobalElements().
178  */
179  void markEntityOwnership (const entityPID_Type& entityPID);
180 
181  //! Private Data Members
182  //@{
201  //@}
202 }; // class MeshPartBuilder
203 
204 // IMPLEMENTATION
205 
206 template<typename MeshType>
208  const UInt overlap,
209  const commPtr_Type& comm)
210  : M_nBoundaryVertices (0),
211  M_nBoundaryRidges (0),
212  M_nBoundaryFacets (0),
213  M_elementVertices (MeshType::elementShape_Type::S_numVertices),
214  M_elementFacets (MeshType::elementShape_Type::S_numFacets),
215  M_elementRidges (MeshType::elementShape_Type::S_numRidges),
216  M_facetVertices (MeshType::facetShape_Type::S_numVertices),
217  M_originalMesh (mesh),
218  M_meshPart(),
219  M_partIndex (0),
220  M_overlap (overlap),
221  M_comm (comm)
222 {}
223 
224 template<typename MeshType>
225 void MeshPartBuilder<MeshType>::run (const meshPtr_Type& meshPart,
226  const idTablePtr_Type& graph,
227  const entityPID_Type& entityPIDList,
228  const UInt partIndex)
229 {
230  M_meshPart = meshPart;
231  M_partIndex = partIndex;
232 
233  const idList_Type& elementList = * (graph->at (partIndex) );
234 
236  if ( M_overlap != 0)
237  {
238  gh.extendGraphFE ( graph,
239  entityPIDList.points,
240  M_overlap,
241  M_partIndex );
242  }
243 
244  constructLocalMesh (elementList);
249 
250  finalSetup();
251 
252  markEntityOwnership (entityPIDList);
253 
254 }
255 
256 template<typename MeshType>
258  const std::vector<Int>& elementList)
259 {
260  std::map<Int, Int>::iterator im;
261  std::set<Int>::iterator is;
262 
263  Int count = 0;
264  UInt ielem;
265  UInt inode;
266 
267  count = 0;
268  // cycle on local element's ID
269 
270  for (UInt jj = 0; jj < elementList.size(); ++jj)
271  {
272  ielem = elementList[jj];
273  M_localElements.push_back (ielem);
274 
275  // cycle on element's nodes
276  for (UInt ii = 0; ii < M_elementVertices; ++ii)
277  {
278  inode = M_originalMesh->element (ielem).point (ii).id();
279  im = M_globalToLocalVertex.find (inode);
280 
281  // if the node is not yet present in the list of local nodes,
282  // then add it
283  if (im == M_globalToLocalVertex.end() )
284  {
285  M_globalToLocalVertex.insert (std::make_pair (inode, count) );
286  ++count;
287  // store here the global numbering of the node
288  M_localVertices.push_back (
289  M_originalMesh->element (ielem).point (ii).id() );
290  }
291  }
292 
293  // cycle on element's edges
294  for (UInt ii = 0; ii < M_elementRidges; ++ii)
295  {
296  // store here the global numbering of the edge
297  M_localRidges.insert (M_originalMesh->localRidgeId (ielem, ii) );
298  }
299 
300  // cycle on element's faces
301  for (UInt ii = 0; ii < M_elementFacets; ++ii)
302  {
303  // store here the global numbering of the face
304  M_localFacets.insert (M_originalMesh->localFacetId (ielem, ii) );
305  }
306  }
307 }
308 
309 template<typename MeshType>
311 {
312  UInt inode;
313  std::vector<Int>::iterator it;
314 
316  M_meshPart->pointList.reserve (M_localVertices.size() );
317  // guessing how many boundary points on this processor.
318  M_meshPart->_bPoints.reserve (M_originalMesh->numBPoints()
319  * M_localVertices.size()
320  / M_originalMesh->numBPoints()
321  );
322  inode = 0;
323  typename MeshType::point_Type* pp = 0;
324 
325  // loop in the list of local nodes:
326  // in this loop inode is the local numbering of the points
327  for (it = M_localVertices.begin();
328  it != M_localVertices.end(); ++it, ++inode)
329  {
330  // create a boundary point in the local mesh, if needed
331  bool boundary = M_originalMesh->isBoundaryPoint (*it);
332  if (boundary)
333  {
334  ++M_nBoundaryVertices;
335  }
336 
337  pp = & (M_meshPart->addPoint (boundary, false) );
338  *pp = M_originalMesh->point ( *it );
339 
340  pp->setLocalId ( inode );
341  }
342 }
343 
344 template<typename MeshType>
346 {
347  Int count;
348  std::map<Int, Int>::iterator im;
349  std::vector<Int>::iterator it;
350  count = 0;
351  UInt inode;
352 
353  typename MeshType::element_Type* pv = 0;
354 
355  M_meshPart->elementList().reserve (M_localElements.size() );
356 
357  // loop in the list of local elements
358  // CAREFUL! in this loop inode is the global numbering of the points
359  // We insert the local numbering of the nodes in the local volume list
360  for (it = M_localElements.begin();
361  it != M_localElements.end(); ++it, ++count)
362  {
363  pv = & (M_meshPart->addElement() );
364  *pv = M_originalMesh->element ( *it );
365  pv->setLocalId ( count );
366 
367  M_globalToLocalElement.insert (std::make_pair (pv->id(),
368  pv->localId() ) );
369 
370  for (ID id = 0; id < M_elementVertices; ++id)
371  {
372  inode = M_originalMesh->element (*it).point (id).id();
373  // im is an iterator to a map element
374  // im->first is the key (i. e. the global ID "inode")
375  // im->second is the value (i. e. the local ID "count")
376  im = M_globalToLocalVertex.find (inode);
377  pv->setPoint (id, M_meshPart->point ( (*im).second ) );
378  }
379  }
380 }
381 
382 template<typename MeshType>
384 {
385  Int count;
386  std::map<Int, Int>::iterator im;
387  std::set<Int>::iterator is;
388 
389  typename MeshType::ridge_Type* pe;
390  UInt inode;
391  count = 0;
392 
393  M_nBoundaryRidges = 0;
394  M_meshPart->ridgeList().reserve (M_localRidges.size() );
395 
396  // loop in the list of local edges
397  for (is = M_localRidges.begin(); is != M_localRidges.end(); ++is, ++count)
398  {
399  // create a boundary edge in the local mesh, if needed
400  bool boundary = (M_originalMesh->isBoundaryRidge (*is) );
401  if (boundary)
402  {
403  // create a boundary edge in the local mesh, if needed
404  ++M_nBoundaryRidges;
405  }
406 
407  pe = & (M_meshPart->addRidge (boundary) );
408  *pe = M_originalMesh->ridge ( *is );
409 
410  pe->setLocalId (count);
411 
412  for (ID id = 0; id < 2; ++id)
413  {
414  inode = M_originalMesh->ridge (*is).point (id).id();
415  // im is an iterator to a map element
416  // im->first is the key (i. e. the global ID "inode")
417  // im->second is the value (i. e. the local ID "count")
418  im = M_globalToLocalVertex.find (inode);
419  pe->setPoint (id, M_meshPart->pointList ( (*im).second) );
420  }
421  }
422 }
423 
424 template<typename MeshType>
426 {
427  Int count;
428  std::map<Int, Int>::iterator im;
429  std::set<Int>::iterator is;
430 
431  typename MeshType::facet_Type* pf = 0;
432 
433  UInt inode;
434  count = 0;
435 
436  M_nBoundaryFacets = 0;
437  M_meshPart->facetList().reserve (M_localFacets.size() );
438 
439  // loop in the list of local faces
440  for (is = M_localFacets.begin(); is != M_localFacets.end(); ++is, ++count)
441  {
442  // create a boundary face in the local mesh, if needed
443  bool boundary = (M_originalMesh->isBoundaryFacet (*is) );
444  if (boundary)
445  {
446  ++M_nBoundaryFacets;
447  }
448 
449  Int elem1 = M_originalMesh->facet (*is).firstAdjacentElementIdentity();
450  Int elem2 = M_originalMesh->facet (*is).secondAdjacentElementIdentity();
451 
452  // find the mesh elements adjacent to the face
453  im = M_globalToLocalElement.find (elem1);
454 
455  ID localElem1;
456 
457  if (im == M_globalToLocalElement.end() )
458  {
459  localElem1 = NotAnId;
460  }
461  else
462  {
463  localElem1 = (*im).second;
464  }
465 
466  im = M_globalToLocalElement.find (elem2);
467 
468  ID localElem2;
469  if (im == M_globalToLocalElement.end() )
470  {
471  localElem2 = NotAnId;
472  }
473  else
474  {
475  localElem2 = (*im).second;
476  }
477 
478  pf = & (M_meshPart->addFacet (boundary) );
479  *pf = M_originalMesh->facet ( *is );
480 
481  pf->setLocalId ( count );
482 
483  for (ID id = 0; id < M_originalMesh->facet (*is).S_numLocalVertices; ++id)
484  {
485  inode = pf->point (id).id();
486  im = M_globalToLocalVertex.find (inode);
487  pf->setPoint (id, M_meshPart->pointList ( (*im).second) );
488  }
489 
490  // true if we are on a subdomain border
491  ID ghostElem = ( localElem1 == NotAnId ) ? elem1 : elem2;
492 
493  if ( !boundary && ( localElem1 == NotAnId || localElem2 == NotAnId ) )
494  {
495  // set the flag for faces on the subdomain border
496  pf->setFlag ( EntityFlags::SUBDOMAIN_INTERFACE );
497  // set the flag for all points on that face
498  for ( UInt pointOnFacet = 0; pointOnFacet < MeshType::facet_Type::S_numLocalPoints; pointOnFacet++ )
499  {
500  M_meshPart->point ( pf->point ( pointOnFacet ).localId() ).setFlag ( EntityFlags::SUBDOMAIN_INTERFACE );
501  }
502  }
503 
504  ASSERT ( (localElem1 != NotAnId) || (localElem2 != NotAnId), "A hanging facet in mesh partitioner!");
505 
506  if ( localElem1 == NotAnId )
507  {
508  pf->firstAdjacentElementIdentity() = localElem2;
509  pf->firstAdjacentElementPosition() = M_originalMesh->facet (*is).secondAdjacentElementPosition();
510  pf->secondAdjacentElementIdentity() = ghostElem;
511  pf->secondAdjacentElementPosition() = NotAnId;
512  pf->reversePoints();
513  }
514  else if ( localElem2 == NotAnId )
515  {
516  pf->firstAdjacentElementIdentity() = localElem1;
517  pf->firstAdjacentElementPosition() = M_originalMesh->facet (*is).firstAdjacentElementPosition();
518  pf->secondAdjacentElementIdentity() = ghostElem;
519  pf->secondAdjacentElementPosition() = NotAnId;
520  }
521  else
522  {
523  pf->firstAdjacentElementIdentity() = localElem1;
524  pf->firstAdjacentElementPosition() = M_originalMesh->facet (*is).firstAdjacentElementPosition();
525  pf->secondAdjacentElementIdentity() = localElem2;
526  pf->secondAdjacentElementPosition() = M_originalMesh->facet (*is).secondAdjacentElementPosition();
527  }
528 
529  }
530  M_meshPart->setLinkSwitch ("HAS_ALL_FACETS");
531  M_meshPart->setLinkSwitch ("FACETS_HAVE_ADIACENCY");
532 }
533 
534 template<typename MeshType>
535 void MeshPartBuilder<MeshType>::finalSetup()
536 {
537  UInt nVolumes = M_localElements.size();
538  UInt nNodes = M_localVertices.size();
539  UInt nEdges = M_localRidges.size();
540  UInt nFaces = M_localFacets.size();
541 
542  M_meshPart->setMaxNumPoints (nNodes, true);
543  M_meshPart->setMaxNumEdges (nEdges, true);
544  M_meshPart->setMaxNumFaces (nFaces, true);
545  M_meshPart->setMaxNumVolumes ( nVolumes, true);
546 
547  M_meshPart->setMaxNumGlobalPoints (M_originalMesh->numPoints() );
548  M_meshPart->setNumGlobalVertices (M_originalMesh->numVertices() );
549  M_meshPart->setMaxNumGlobalRidges (M_originalMesh->numRidges() );
550  M_meshPart->setMaxNumGlobalFacets (M_originalMesh->numFacets() );
551 
552  M_meshPart->setMaxNumGlobalElements (M_originalMesh->numElements() );
553  M_meshPart->setNumBoundaryFacets (M_nBoundaryFacets);
554 
555  M_meshPart->setNumBPoints (M_nBoundaryVertices);
556  M_meshPart->setNumBoundaryRidges (M_nBoundaryRidges);
557 
558  M_meshPart->setNumVertices (nNodes );
559  M_meshPart->setNumBVertices (M_nBoundaryVertices);
560 
561  if (MeshType::S_geoDimensions == 3)
562  {
563  M_meshPart->updateElementRidges();
564  }
565 
566  M_meshPart->updateElementFacets();
567 }
568 
569 template<typename MeshType>
570 void
571 MeshPartBuilder<MeshType>::markEntityOwnership (const entityPID_Type& entityPID)
572 {
573  // mark owned entities by each partition as described in M_entityPID
574  //M_entityPID or flags should be exported and read back to make it work
575  for ( UInt e = 0; e < M_meshPart->numElements(); e++ )
576  {
577  typename MeshType::element_Type& element = M_meshPart->element (e);
578  if (entityPID.elements[element.id()] != static_cast<Int>(M_partIndex) )
579  {
580  element.setFlag ( EntityFlags::GHOST );
581  }
582  }
583 
584  for ( UInt f = 0; f < M_meshPart->numFacets(); f++ )
585  {
586  typename MeshType::facet_Type& facet = M_meshPart->facet (f);
587  if (entityPID.facets[facet.id()] != static_cast<Int>(M_partIndex) )
588  {
589  facet.setFlag ( EntityFlags::GHOST );
590  }
591  }
592 
593  for ( UInt r = 0; r < M_meshPart->numRidges(); r++ )
594  {
595  typename MeshType::ridge_Type& ridge = M_meshPart->ridge (r);
596  if (entityPID.ridges[ridge.id()] != static_cast<Int>(M_partIndex) )
597  {
598  ridge.setFlag ( EntityFlags::GHOST );
599  }
600  }
601 
602  for ( UInt p = 0; p < M_meshPart->numPoints(); ++p )
603  {
604  typename MeshType::point_Type& point = M_meshPart->point (p);
605  if (entityPID.points[point.id()] != static_cast<Int>(M_partIndex) )
606  {
607  point.setFlag ( EntityFlags::GHOST );
608  }
609  }
610 }
611 
612 template<typename MeshType>
613 void MeshPartBuilder<MeshType>::reset()
614 {
616  M_nBoundaryRidges = 0;
617  M_nBoundaryFacets = 0;
618 
619  M_localVertices.resize (0);
620  M_localRidges.clear();
621  M_localFacets.clear();
622  M_localElements.resize (0);
623  M_globalToLocalVertex.clear();
624  M_globalToLocalElement.clear();
625 
626  M_partIndex = 0;
627 }
628 
629 }// namespace LifeV
630 
631 #endif // MESH_PART_BUILDER_H
void constructRidges()
Construct edges.
void constructNodes()
Construct nodes.
std::shared_ptr< mesh_Type > meshPtr_Type
std::set< Int > M_localFacets
void run(const meshPtr_Type &meshPart, const idTablePtr_Type &graph, const entityPID_Type &entityPIDList, const UInt partIndex)
Run part builder.
std::set< Int > M_localRidges
MeshPartBuilder(const meshPtr_Type &mesh, const UInt overlap, const commPtr_Type &comm)
Constructor.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
void updateInverseJacobian(const UInt &iQuadPt)
std::vector< Int > M_localVertices
void constructFacets()
Construct faces.
void reset()
Resets the MeshPartBuilder object to the initial state.
std::map< Int, Int > M_globalToLocalVertex
~MeshPartBuilder()
Empty destructor.
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
std::map< Int, Int > M_globalToLocalElement
std::vector< LifeV::Int > idList_Type
Definition: GraphUtil.hpp:60
std::shared_ptr< Epetra_Comm > commPtr_Type
void constructLocalMesh(const std::vector< Int > &elementList)
Private Methods.
const std::map< Int, Int > & globalToLocalElement() const
Class that builds a mesh part, after the graph has been partitioned.
std::vector< Int > M_localElements
std::shared_ptr< idTable_Type > idTablePtr_Type
Definition: GraphUtil.hpp:63
void constructElements()
Construct volumes.
void finalSetup()
Final setup of local mesh.
void markEntityOwnership(const entityPID_Type &entityPID)
Mark entity ownership.
void importFromHDF5(std::string const &fileName="ghostmap")
Import neighbor lists to an hdf5 file.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
UInt M_nBoundaryVertices
Private Data Members.