LifeV
GhostHandler.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 class to manage ghost data across procs
30 
31  @author Antonio Cervone <ant.cervone@gmail.com>
32 
33  @date 27-10-2011
34 */
35 
36 #ifndef _GHOSTHANDLER_HPP_
37 #define _GHOSTHANDLER_HPP_
38 
39 #include <bitset>
40 
41 #ifdef HAVE_HDF5
42 #include <EpetraExt_HDF5.h>
43 #endif
44 
45 #include <lifev/core/LifeV.hpp>
46 #include <lifev/core/util/LifeChronoManager.hpp>
47 #include <lifev/core/array/MapEpetra.hpp>
48 #include <lifev/core/mesh/NeighborMarker.hpp>
49 
50 #ifdef HAVE_LIFEV_DEBUG
51 //#define LIFEV_GHOSTHANDLER_DEBUG 1
52 #endif
53 
54 namespace LifeV
55 {
56 
57 typedef std::bitset<4> NeighborType;
58 
64 
65 //! GhostHandler
66 /*!
67  This class manages neighborhood information across processes.
68  The aim is to have the possibility to build overlapping maps
69  in order to ease the retrieving of ghosted values. The class
70  offers also the possibility to build phisically overlapped
71  meshes that do not require communication to retrieve mesh
72  information from adjacent elements.
73  */
74 template <typename MeshType>
76 {
77 public:
78 
79  //! @name Public Types
80  //@{
81 
82  typedef MeshType mesh_Type;
96 
97  //@}
98 
99  //! @name Constructors & Destructors
100  //@{
101  //! Constructor
102  /*!
103  * @param comm. Communicator
104  */
105  explicit GhostHandler ( commPtr_Type const& comm );
106 
107  //! Constructor
108  /*!
109  * @param fullMesh. Original mesh, before partitioning
110  * @param comm. Communicator
111  */
112  GhostHandler ( meshPtr_Type fullMesh, commPtr_Type const& comm );
113 
114  //! Constructor
115  /*!
116  * @param fullMesh. Original mesh, before partitioning
117  * @param localMesh. Local mesh of the current proc
118  * @param map. Original map without overlapping
119  * @param comm. Communicator
120  */
121  GhostHandler ( meshPtr_Type fullMesh,
122  meshPtr_Type localMesh,
123  mapPtr_Type map,
124  commPtr_Type const& comm );
125 
126  //! Destructor
128 
129  //@}
130 
131  //! @name Get Methods
132  //@{
133 
134  //! Full mesh getter
136  {
137  return *M_fullMesh;
138  }
139 
140  //! Local mesh getter
142  {
143  return *M_localMesh;
144  }
145 
146  //! Standard map getter
147  map_Type const& map()
148  {
149  return *M_map;
150  }
151 
152  //! List of point neighbors to a point (identified by the global ID)
154  {
155  ASSERT ( !M_pointPointNeighborsList.empty(), "M_pointPointNeighborsList is empty" );
157  }
158 
159  //! List of edge neighbors to a point (identified by the global ID)
161  {
162  ASSERT ( !M_pointEdgeNeighborsList.empty(), "M_pointEdgeNeighborsList is empty" );
164  }
165 
166  //! List of element neighbors to a point (identified by the global ID)
168  {
169  ASSERT ( !M_pointElementNeighborsList.empty(), "M_pointElementNeighborsList is empty" );
171  }
172 
173  //@}
174 
175  //! @name Set Methods
176  //@{
177 
178  //! Set verbosity
179  /*!
180  * @param verbose
181  */
182  void setVerbose ( const bool& verbose )
183  {
184  M_verbose = verbose && ( M_me == 0 );
185  }
186 
187  //@}
188 
189  //! @name General Methods
190  //@{
191 
192  //! Initialize neighbors list
193  void setUpNeighbors ( NeighborType const neighborType = ALL_NEIGHBORS );
194 
195  //! Release pointers to full and local mesh
196  void release();
197 
198  //! Clean up neighbor lists
199  void clean ( NeighborType const neighborType = ALL_NEIGHBORS );
200 
201 #ifdef HAVE_HDF5
202  //! Export neighbor lists to an hdf5 file
203  /*!
204  * @param fileName. Name of the file to write
205  * @param truncate. Must be true when the file already exists on disk
206  */
207  void exportToHDF5 ( std::string const& fileName = "ghostmap", bool const& truncate = true );
208 
209  //! Import neighbor lists to an hdf5 file
210  /*!
211  * @param fileName. Name of the file to write
212  */
213  void importFromHDF5 ( std::string const& fileName = "ghostmap" );
214 #endif // HAVE_HDF5
215 
216  //! Create point neighbors to points and store them in the NeighborMarker
217  void createPointNeighbors();
218 
219  //! Create the list of point neighbors to points
221 
222  //! Create the list of point neighbors to points that are in the given list of MarkerIDs
223  /*!
224  * @param flags. The list of MarkerIDs to restrict to.
225  */
227 
228  //! Create neighbors to a given point, with a specified number of generations
229  /*!
230  * @param globalID. ID of the point to be examined.
231  * @param nCircles. Number of circles (generations) to consider.
232  * @return the set of neighbors global IDs
233  */
234  neighbors_Type circleNeighbors ( UInt globalID, UInt nCircles = 1 );
235 
236  //! Create neighbors to a given point within a specified radius
237  /*!
238  * @param globalID. ID of the point to be examined.
239  * @param radius. The value of the circle radius within which neighbors are included
240  * @return the set of neighbors global IDs
241  */
242  neighbors_Type neighborsWithinRadius ( UInt globalID, Real radius );
243 
244  //! Create the list of edge neighbors to the points
246 
247  //! Create the list of element neighbors to the points
249 
250  //! Create an overlapped map on points
251  /*! Create a map based on points, expanding it across suddomain interfaces
252  * with overlap 1, using NeighborMarker.
253  */
255 
256  //! Create an overlapped map on points
257  /*! Create a map based on points, expanding it across suddomain interfaces
258  * with generic overlap.
259  * @param overlap. Level of overlap between subdomains
260  * @return the overlapped map
261  */
262  map_Type& ghostMapOnPoints ( UInt overlap );
263 
264  //! Create an overlapped map on edges
265  /*! Create a map based on edges, expanding it across suddomain interfaces
266  * with generic overlap.
267  * @param overlap. Level of overlap between subdomains
268  * @return the overlapped map
269  */
270  map_Type& ghostMapOnEdges ( UInt overlap );
271 
272  //! Create an overlapped map on elements for Finite Volumes
273  /*! Create a map based on elements, expanding it across suddomain interfaces.
274  * The elements added are only those that share a facet with the current subdomain.
275  * This type of map is typically used for Finite Volumes.
276  * @return the overlapped map
277  */
278  // ghostMapOnElementsCommonFacet
280 
281  //! Create an overlapped map on elements for Finite Elements
282  /*! Create a map based on elements, expanding it across suddomain interfaces.
283  * The elements added are all those that share a point with the current subdomain.
284  * This type of map is typically used for Finite Elements.
285  * @param overlap. Level of overlap between subdomains
286  */
287  // ghostMapOnElementsCommonPoints
288  map_Type& ghostMapOnElementsFE ( UInt overlap );
289 
290  //! Extend the subdomains graph of the given overlap.
291  /*!
292  * This method enriches each subdomain with the closest elements such that
293  * the partitions have the required overlap.
294  * \param elemGraph. The list of subdomain elements
295  * \param entityPID. Info about proc ownership of each mesh entity.
296  * \param overlap. Level of overlap between partitions.
297  */
298  void extendGraphFE ( graphPtr_Type elemGraph, idList_Type const& pointPID, UInt overlap );
299 
300  //! Extend the subdomains graph of the given overlap.
301  /*!
302  * This method enriches each subdomain with the closest elements such that
303  * the partitions have the required overlap.
304  * \param elemGraph. The list of subdomain elements
305  * \param entityPID. Info about proc ownership of each mesh entity.
306  * \param overlap. Level of overlap between partitions.
307  */
308  void extendGraphFE ( const vertexPartitionPtr_Type& elemGraph,
309  idList_Type const& pointPID,
310  UInt overlap,
311  UInt partIndex);
312 
313  //! showMe method
314  void showMe ( bool const verbose = false, std::ostream& out = std::cout );
315 
316  //@}
317 
318 protected:
319 
320  //! @name Ghost Maps
321  //@{
322 
327 
328  //@}
329 
330  //! @name Protected Members
331  //@{
332 
337  UInt const M_me;
338 
342 
343  bool M_verbose;
344 #ifdef LIFEV_GHOSTHANDLER_DEBUG
346 #endif
347  //@}
348 };
349 
350 template <typename MeshType>
351 GhostHandler<MeshType>::GhostHandler ( commPtr_Type const& comm ) :
352  M_fullMesh(),
353  M_localMesh(),
354  M_map(),
355  M_comm ( comm ),
356  M_me ( comm->MyPID() ),
360  M_verbose ( 0 )
361 #ifdef LIFEV_GHOSTHANDLER_DEBUG
362  , M_debugOut ( ( "gh." + ( comm->NumProc() > 1 ? std::to_string ( M_me ) : "s" ) + ".out" ).c_str() )
363 #endif
364 {
365 }
366 
367 template <typename MeshType>
368 GhostHandler<MeshType>::GhostHandler ( meshPtr_Type fullMesh,
369  meshPtr_Type localMesh,
370  mapPtr_Type map,
371  commPtr_Type const& comm ) :
372  M_fullMesh ( fullMesh ),
373  M_localMesh ( localMesh ),
374  M_map ( map ),
375  M_comm ( comm ),
376  M_me ( comm->MyPID() ),
380  M_verbose ( 0 )
381 #ifdef LIFEV_GHOSTHANDLER_DEBUG
382  , M_debugOut ( ( "gh." + ( comm->NumProc() > 1 ? std::to_string ( M_me ) : "s" ) + ".out" ).c_str() )
383 #endif
384 {
385 }
386 
387 template <typename MeshType>
388 GhostHandler<MeshType>::GhostHandler ( meshPtr_Type fullMesh,
389  commPtr_Type const& comm ) :
390  M_fullMesh ( fullMesh ),
391  M_comm ( comm ),
392  M_me ( comm->MyPID() ),
396  M_verbose ( 0 )
397 #ifdef LIFEV_GHOSTHANDLER_DEBUG
398  , M_debugOut ( ( "gh." + ( comm->NumProc() > 1 ? std::to_string ( M_me ) : "s" ) + ".out" ).c_str() )
399 #endif
400 {
401 }
402 
403 template <typename MeshType>
404 void GhostHandler<MeshType>::setUpNeighbors ( NeighborType const neighborType )
405 {
406  if ( (neighborType & POINT_NEIGHBORS) != 0 )
407  {
408  this->createPointPointNeighborsList();
409  }
410  if ( (neighborType & RIDGE_NEIGHBORS) != 0 )
411  {
412  this->createPointEdgeNeighborsList();
413  }
414  if ( (neighborType & ELEMENT_NEIGHBORS) != 0 )
415  {
416  this->createPointElementNeighborsList();
417  }
418 }
419 
420 template <typename MeshType>
421 void GhostHandler<MeshType>::release()
422 {
423  M_fullMesh.reset();
424  M_localMesh.reset();
425 }
426 
427 template <typename MeshType>
428 void GhostHandler<MeshType>::clean ( NeighborType const neighborType )
429 {
430  if ( (neighborType & POINT_NEIGHBORS) != 0 )
431  {
432  clearVector ( M_pointPointNeighborsList );
433  }
434  if ( (neighborType & RIDGE_NEIGHBORS) != 0 )
435  {
436  clearVector ( M_pointEdgeNeighborsList );
437  }
438  if ( (neighborType & ELEMENT_NEIGHBORS) != 0 )
439  {
440  clearVector ( M_pointElementNeighborsList );
441  }
442 }
443 
444 #ifdef HAVE_HDF5
445 
446 namespace
447 {
448 
450 {
451  // copy the map into vectors
452  ASSERT ( list.size() > 0, "the map " + name + " is empty!" )
453  std::vector<Int> offsets ( list.size() + 1 );
454  std::vector<Int> values;
455  Int sum ( 0 );
456  for ( UInt i ( 0 ); i < list.size(); i++ )
457  {
458  sum += list[ i ].size();
459  offsets[ i + 1 ] = sum;
460  for ( neighbors_Type::const_iterator j ( list[ i ].begin() ); j != list[ i ].end(); ++j )
461  {
462  values.push_back ( *j );
463  }
464  }
465 
466  // Save the vectors into the file
467  file.Write ( name, "offsetSize", static_cast<Int> ( offsets.size() ) );
468  file.Write ( name, "offsets", H5T_NATIVE_INT, offsets.size(), &offsets[ 0 ] );
469  file.Write ( name, "valueSize", static_cast<Int> ( values.size() ) );
470  file.Write ( name, "values", H5T_NATIVE_INT, values.size(), &values[ 0 ] );
471 
472  //#ifdef LIFEV_GHOSTHANDLER_DEBUG
473  // std::cerr << name << std::endl;
474  // for ( UInt i ( 0 ); i < map.size(); i++ )
475  // {
476  // std::cerr << i << "> ";
477  // for ( neighborList_Type::const_iterator j ( map[ i ].begin() ); j != map[ i ].end(); ++j )
478  // {
479  // std::cerr << *j << " ";
480  // }
481  // std::cerr <<std::endl;
482  // }
483  //#endif
484 }
485 
487 {
488  // Read the vectors from the file
489  Int offsetSize;
490  file.Read ( name, "offsetSize", offsetSize );
492  file.Read ( name, "offsets", H5T_NATIVE_INT, offsetSize, &offsets[ 0 ] );
493  Int valueSize;
494  file.Read ( name, "valueSize", valueSize );
495  std::vector<Int> values ( valueSize );
496  file.Read ( name, "values", H5T_NATIVE_INT, valueSize, &values[ 0 ] );
497 
498  // setup the map
499  list.resize ( offsetSize - 1 );
500  for ( Int i ( 0 ); i < offsetSize - 1; i++ )
501  {
502  for ( Int j ( offsets[ i ] ); j < offsets[ i + 1 ]; j++ )
503  {
504  list[ i ].insert ( values[ j ] );
505  }
506  }
507 
508  //#ifdef LIFEV_GHOSTHANDLER_DEBUG
509  // std::cerr << name << std::endl;
510  // for ( UInt i ( 0 ); i < map.size(); i++ )
511  // {
512  // std::cerr << i << "> ";
513  // for ( neighborList_Type::const_iterator j ( map[ i ].begin() ); j != map[ i ].end(); ++j )
514  // {
515  // std::cerr << *j << " ";
516  // }
517  // std::cerr <<std::endl;
518  // }
519  //#endif
520 }
521 
522 }
523 
524 template <typename MeshType>
526 {
527  EpetraExt::HDF5 HDF5 ( *M_comm );
528 
529  if ( truncate )
530  {
531  // Create and open the file / Truncate and open the file
532  HDF5.Create ( ( fileName + ".h5" ).data() );
533  }
534  else
535  {
536  // Open an existing file without truncating it
537  HDF5.Open ( ( fileName + ".h5" ).data() );
538  }
539 
540  // Check if the file is created
541  if ( !HDF5.IsOpen () )
542  {
543  std::cerr << "Unable to create " + fileName + ".h5";
544  abort();
545  }
546 
547  writeNeighborMap ( HDF5, M_pointPointNeighborsList, "pointPointNeighborsMap" );
548  writeNeighborMap ( HDF5, M_pointEdgeNeighborsList, "pointEdgeNeighborsMap" );
549  writeNeighborMap ( HDF5, M_pointElementNeighborsList, "pointElementNeighborsMap" );
550 
551  // Close the file
552  HDF5.Close();
553 }
554 
555 template <typename MeshType>
557 {
558  EpetraExt::HDF5 HDF5 ( *M_comm );
559 
560  // Open an existing file
561  HDF5.Open ( ( fileName + ".h5" ).data() );
562 
563  // Check if the file is created
564  if ( !HDF5.IsOpen () )
565  {
566  std::cerr << "Unable to open " + fileName + ".h5";
567  abort();
568  }
569 
570  readNeighborMap ( HDF5, M_pointPointNeighborsList, "pointPointNeighborsMap" );
571  readNeighborMap ( HDF5, M_pointEdgeNeighborsList, "pointEdgeNeighborsMap" );
572  readNeighborMap ( HDF5, M_pointElementNeighborsList, "pointElementNeighborsMap" );
573 
574  // Close the file
575  HDF5.Close();
576 }
577 
578 #endif // HAVE_HDF5
579 
580 //! this routine generates point neighbors for the given mesh
581 /*! the routine assumes that the mesh is not yet partitioned or reordered
582  * (i.e. the local id and the global id are the same).
583  * if this is not true the method should be changed to use a more
584  * expensive STL find on the mesh points to get the correct point that has
585  * the given global id or construct a globalToLocal map beforehand.
586  */
587 template <typename MeshType>
589 {
590  // @TODO: ASSERT_COMPILE_TIME that MeshType::pointMarker == NeighborMarker
591  // this guarantees that the pointNeighbors structure is available.
592 
593  // generate point neighbors by watching edges
594  // note: this can be based also on faces or volumes
595  for ( UInt ie = 0; ie < M_fullMesh->numEdges(); ie++ )
596  {
597  ID id0 = M_fullMesh->edge ( ie ).point ( 0 ).id();
598  ID id1 = M_fullMesh->edge ( ie ).point ( 1 ).id();
599 
600  ASSERT ( M_fullMesh->point ( id0 ).id() == id0 && M_fullMesh->point ( id1 ).id() == id1,
601  "the mesh has been reordered, the point must be found" );
602 
603  // fill fullMesh points neighboring
604  M_fullMesh->point ( id0 ).pointNeighbors().insert ( id1 );
605  M_fullMesh->point ( id1 ).pointNeighbors().insert ( id0 );
606  }
607 
608  // update localMesh points
609  for ( UInt ip = 0; ip < M_localMesh->numPoints(); ip++ )
610  {
611  M_localMesh->point ( ip ).pointNeighbors() = M_fullMesh->point ( M_localMesh->point ( ip ).id() ).pointNeighbors();
612  }
613 }
614 
615 template <typename MeshType>
617 {
618  M_pointPointNeighborsList.resize ( M_fullMesh->numGlobalPoints() );
619  // generate point neighbors by watching edges
620  // note: this can be based also on faces or volumes
621  for ( UInt ie = 0; ie < M_fullMesh->numEdges(); ie++ )
622  {
623  ID id0 = M_fullMesh->edge ( ie ).point ( 0 ).id();
624  ID id1 = M_fullMesh->edge ( ie ).point ( 1 ).id();
625 
626  ASSERT ( M_fullMesh->point ( id0 ).id() == id0 && M_fullMesh->point ( id1 ).id() == id1,
627  "the mesh has been reordered, the point must be found" );
628 
629  M_pointPointNeighborsList[ id0 ].insert ( id1 );
630  M_pointPointNeighborsList[ id1 ].insert ( id0 );
631  }
632 
633 #ifdef LIFEV_GHOSTHANDLER_DEBUG
634  M_debugOut << "M_pointPointNeighborsList on proc " << M_me << std::endl;
635  for ( UInt i = 0; i < M_pointPointNeighborsList.size(); i++ )
636  {
637  M_debugOut << i << ": ";
638  for ( neighbors_Type::const_iterator it = M_pointPointNeighborsList[ i ].begin();
639  it != M_pointPointNeighborsList[ i ].end(); ++it )
640  {
641  M_debugOut << *it << " ";
642  }
643  M_debugOut << std::endl;
644  }
645 #endif
646 }
647 
648 namespace
649 {
650 
651 inline bool isInside ( markerID_Type const& pointMarker, std::vector<int> const& markerIDList )
652 {
653  for ( UInt i = 0; i < markerIDList.size(); ++i)
654  if ( pointMarker == markerIDList[i] )
655  {
656  return true;
657  }
658  return false;
659 }
660 
661 }
662 
663 template <typename MeshType>
665 {
666  M_pointPointNeighborsList.resize ( M_fullMesh->numGlobalPoints() );
667  // generate point neighbors by watching edges
668  // note: this can be based also on faces or volumes
669  for ( UInt ie = 0; ie < M_fullMesh->numEdges(); ie++ )
670  {
671  ID id0 = M_fullMesh->edge ( ie ).point ( 0 ).id();
672  ID id1 = M_fullMesh->edge ( ie ).point ( 1 ).id();
673 
674  ASSERT ( M_fullMesh->point ( id0 ).id() == id0 && M_fullMesh->point ( id1 ).id() == id1,
675  "the mesh has been reordered, the point must be found" );
676 
677  if ( isInside (M_fullMesh->edge ( ie ).point ( 1 ).markerID(), flags) )
678  {
679  M_pointPointNeighborsList[ id0 ].insert ( id1 );
680  }
681 
682  if ( isInside (M_fullMesh->edge ( ie ).point ( 0 ).markerID(), flags) )
683  {
684  M_pointPointNeighborsList[ id1 ].insert ( id0 );
685  }
686 
687  //if(M_fullMesh->edge( ie ).point( 1 ).markerID()==20 || M_fullMesh->edge( ie ).point( 1 ).markerID()==1)
688  // M_pointPointNeighborsList[ id0 ].insert( id1 );
689 
690  //if(M_fullMesh->edge( ie ).point( 0 ).markerID()==20 || M_fullMesh->edge( ie ).point( 0 ).markerID()==1)
691  // M_pointPointNeighborsList[ id1 ].insert( id0 );
692  }
693 }
694 
695 template <typename MeshType>
696 neighbors_Type GhostHandler<MeshType>::circleNeighbors ( UInt globalID, UInt nCircles )
697 {
698  neighbors_Type neighbors;
699  neighbors_Type newEntries;
700  neighbors_Type newNeighbors;
701 
702  neighbors = this->pointPointNeighborsList() [ globalID ];
703 
704  for (UInt i = 0; i < nCircles - 1; ++i)
705  {
706  for (neighbors_Type::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
707  {
708  newEntries = this->pointPointNeighborsList() [*it];
709  for (neighbors_Type::iterator ii = newEntries.begin(); ii != newEntries.end(); ++ii)
710  {
711  newNeighbors.insert (*ii);
712  }
713  }
714 
715  for (neighbors_Type::iterator it = newNeighbors.begin(); it != newNeighbors.end(); ++it)
716  {
717  neighbors.insert(*it);
718  }
719  }
720 
721  return neighbors;
722 }
723 
724 
725 template <typename MeshType>
727 {
728  neighbors_Type neighbors;
729  neighbors_Type newEntries;
730  neighbors_Type newNeighbors;
731  bool isInside = true;
732  Real d = 0;
733  UInt mysize = 0;
734 
735  neighbors = this->pointPointNeighborsList() [globalID];
736 
737  typename mesh_Type::point_Type const& p = M_fullMesh->point (globalID);
738 
739  while (isInside)
740  {
741  for (neighbors_Type::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
742  {
743  newEntries = this->pointPointNeighborsList() [*it];
744  for (neighbors_Type::iterator ii = newEntries.begin(); ii != newEntries.end(); ++ii)
745  {
746  typename mesh_Type::point_Type const& n = M_fullMesh->point (*ii);
747  d = std::sqrt ( ( n.x() - p.x() ) * ( n.x() - p.x() ) +
748  ( n.y() - p.y() ) * ( n.y() - p.y() ) +
749  ( n.z() - p.z() ) * ( n.z() - p.z() ) );
750  if (d < radius)
751  {
752  newNeighbors.insert (*ii);
753  }
754  }
755  }
756 
757  neighbors = newNeighbors;
758 
759  if (neighbors.size() == mysize)
760  {
761  isInside = false;
762  }
763 
764  mysize = neighbors.size();
765 
766  }
767 
768  return neighbors;
769 
770 }
771 
772 template <typename MeshType>
774 {
775  M_pointEdgeNeighborsList.resize ( M_fullMesh->numGlobalPoints() );
776  // generate point neighbors by watching edges
777  // note: this can be based also on faces or volumes
778  for ( UInt ie = 0; ie < M_fullMesh->numEdges(); ie++ )
779  {
780  ID id0 = M_fullMesh->edge ( ie ).point ( 0 ).id();
781  ID id1 = M_fullMesh->edge ( ie ).point ( 1 ).id();
782 
783  ASSERT ( M_fullMesh->point ( id0 ).id() == id0 && M_fullMesh->point ( id1 ).id() == id1,
784  "the mesh has been reordered, the point must be found" );
785 
786  M_pointEdgeNeighborsList[ id0 ].insert ( ie );
787  M_pointEdgeNeighborsList[ id1 ].insert ( ie );
788  }
789 
790 #ifdef LIFEV_GHOSTHANDLER_DEBUG
791  M_debugOut << "M_pointEdgeNeighborsList on proc " << M_me << std::endl;
792  for ( UInt i = 0; i < M_pointEdgeNeighborsList.size(); i++ )
793  {
794  M_debugOut << i << ": ";
795  for ( neighbors_Type::const_iterator it = M_pointEdgeNeighborsList[ i ].begin();
796  it != M_pointEdgeNeighborsList[ i ].end(); ++it )
797  {
798  M_debugOut << *it << " ";
799  }
800  M_debugOut << std::endl;
801  }
802 #endif
803 }
804 
805 template <typename MeshType>
807 {
808  M_pointElementNeighborsList.resize ( M_fullMesh->numGlobalPoints() );
809  // generate element neighbors by cycling on elements
810  for ( UInt ie = 0; ie < M_fullMesh->numElements(); ie++ )
811  {
812  ASSERT ( M_fullMesh->element ( ie ).id() == ie,
813  "the mesh has been reordered, the point must be found" );
814 
815  for ( UInt k = 0; k < mesh_Type::element_Type::S_numPoints; k++ )
816  {
817  ID id ( M_fullMesh->element ( ie ).point ( k ).id() );
818  M_pointElementNeighborsList[ id ].insert ( ie );
819  }
820  }
821 }
822 
823 template <typename MeshType>
824 typename GhostHandler<MeshType>::map_Type& GhostHandler<MeshType>::ghostMapOnPoints()
825 {
826  // if the map has already been created, return it
827  if ( M_ghostMapOnPoints )
828  {
829  return *M_ghostMapOnPoints;
830  }
831 
832  if ( M_verbose )
833  {
834  std::cout << " GH- ghostMapOnPoints()" << std::endl;
835  }
836 
837  // check that the pointNeighbors have been created
838  if ( M_localMesh->point ( 0 ).pointNeighbors().empty() )
839  {
840  if ( M_verbose )
841  {
842  std::cerr << "the pointNeighbors are empty, will be generated now" << std::endl;
843  }
844  this->createPointNeighbors();
845  }
846 
847  // create map
848  M_ghostMapOnPoints.reset ( new map_Type() );
849  map_Type& ghostMap ( *M_ghostMapOnPoints );
850 
851  // use the same Unique map and comm of the original map
852  ghostMap.setMap ( M_map->map ( Unique ), Unique );
853  ghostMap.setComm ( M_comm );
854 
855  // use a set to avoid duplicates
856  std::set<Int> myGlobalElementsSet;
857 
858  // iterate on local mesh points
859  // @todo: this can start from the repeated map and add only neighbors for SUBDOMAIN_INTERFACE marked points
860  for ( UInt k = 0; k < M_localMesh->numPoints(); k++ )
861  {
862  // iterate on each point neighborhood
863  for ( typename mesh_Type::PointMarker::neighborConstIterator_Type neighborIt = M_localMesh->point ( k ).pointNeighbors().begin();
864  neighborIt != M_localMesh->point ( k ).pointNeighbors().end(); ++neighborIt )
865  {
866  myGlobalElementsSet.insert ( *neighborIt );
867  }
868  }
869 
870  std::vector<Int> myGlobalElements ( myGlobalElementsSet.begin(), myGlobalElementsSet.end() );
871 
872  // generate map
873  map_Type::mapPtr_Type repeatedMap ( new Epetra_Map ( -1, myGlobalElements.size(), &myGlobalElements[0], 0, *M_comm ) );
874  ghostMap.setMap ( repeatedMap, Repeated );
875 
876  return *M_ghostMapOnPoints;
877 }
878 
879 template <typename MeshType>
880 typename GhostHandler<MeshType>::map_Type& GhostHandler<MeshType>::ghostMapOnPoints ( UInt overlap )
881 {
882  // if the map has already been created, return it
883  if ( M_ghostMapOnPoints )
884  {
885  return *M_ghostMapOnPoints;
886  }
887 
888  if ( M_verbose )
889  {
890  std::cout << " GH- ghostMapOnPoints( UInt )" << std::endl;
891  }
892 
893  // check that the pointPointNeighborsMap has been created
894  if ( M_pointPointNeighborsList.empty() )
895  {
896  if ( M_verbose )
897  {
898  std::cerr << "the pointPointNeighborsList is empty, will be generated now" << std::endl;
899  }
900  this->createPointPointNeighborsList();
901  }
902 
903  // create map
904  M_ghostMapOnPoints.reset ( new map_Type() );
905  map_Type& ghostMap ( *M_ghostMapOnPoints );
906 
907  // use the same Unique map and comm of the original map
908  ghostMap.setMap ( M_map->map ( Unique ), Unique );
909  ghostMap.setComm ( M_comm );
910 
911  Int* pointer;
912  std::set<Int> myGlobalElementsSet, myOriginalElementsSet;;
913 
914  // get all elements from the repeated map
915  pointer = M_map->map ( Repeated )->MyGlobalElements();
916  for ( Int ii = 0; ii < M_map->map ( Repeated )->NumMyElements(); ++ii, ++pointer )
917  {
918  myOriginalElementsSet.insert ( *pointer );
919  }
920 
921  // todo: optimize this!!
922  // 1: work only on the boundary
923  // 2: copy back only if necessary
924  // repeat on actual points to expand overlap
925  for ( UInt i = 0; i < overlap; i++ )
926  {
927  // iterate on points adding all neighbors
928  for ( std::set<Int>::const_iterator pointIt = myOriginalElementsSet.begin();
929  pointIt != myOriginalElementsSet.end(); ++pointIt )
930  {
931  // iterate on each point neighborhood
932  for ( neighbors_Type::const_iterator neighborIt = M_pointPointNeighborsList[ *pointIt ].begin();
933  neighborIt != M_pointPointNeighborsList[ *pointIt ].end(); ++neighborIt )
934  {
935  myGlobalElementsSet.insert ( *neighborIt );
936  }
937  }
938  myOriginalElementsSet = myGlobalElementsSet;
939  }
940 
941  std::vector<Int> myGlobalElements ( myGlobalElementsSet.begin(), myGlobalElementsSet.end() );
942 
943  // generate map
944  map_Type::mapPtr_Type repeatedMap ( new Epetra_Map ( -1, myGlobalElements.size(), &myGlobalElements[0], 0, *M_comm ) );
945  ghostMap.setMap ( repeatedMap, Repeated );
946 
947  return *M_ghostMapOnPoints;
948 }
949 
950 template <typename MeshType>
951 typename GhostHandler<MeshType>::map_Type& GhostHandler<MeshType>::ghostMapOnEdges ( UInt overlap )
952 {
953  // if the map has already been created, return it
954  if ( M_ghostMapOnEdges )
955  {
956  return *M_ghostMapOnEdges;
957  }
958 
959  if ( M_verbose )
960  {
961  std::cout << " GH- ghostMapOnEdges()" << std::endl;
962  }
963 
964  // check that the pointEdgeNeighborsMap has been created
965  if ( M_pointEdgeNeighborsList.empty() )
966  {
967  if ( M_verbose )
968  {
969  std::cerr << "the pointEdgeNeighborsList is empty, will be generated now" << std::endl;
970  }
971  this->createPointEdgeNeighborsList();
972  }
973 
974  // set up Unique (first) and Repeated edges based on the GHOST flag
975  MapEpetraData mapData;
976  mapData.unique.reserve ( M_localMesh->numEdges() );
977  mapData.repeated.reserve ( M_localMesh->numEdges() );
978  // loop on local mesh edges
979  for ( ID ie = 0; ie < M_localMesh->numEdges(); ie++ )
980  {
981  mapData.repeated.push_back ( M_localMesh->edge ( ie ).id() );
982  if ( M_localMesh->edge ( ie ).isOwned() )
983  {
984  mapData.unique.push_back ( M_localMesh->edge ( ie ).id() );
985  }
986  }
987 
988  M_ghostMapOnEdges.reset ( new map_Type ( mapData, M_comm ) );
989 
990  if ( overlap > 0 )
991  {
992  map_Type& ghostMap ( *M_ghostMapOnEdges );
993 
994  std::set<Int> myGlobalElementsSet;
995  std::set<Int> addedElementsSet;
996 
997  for ( UInt k ( 0 ); k < mapData.repeated.size(); k++ )
998  {
999  typename mesh_Type::edge_Type const& edge = M_fullMesh->edge ( mapData.repeated[ k ] );
1000  for ( UInt edgePoint = 0; edgePoint < mesh_Type::edge_Type::S_numPoints; edgePoint++ )
1001  {
1002  addedElementsSet.insert ( edge.point ( edgePoint ).id() );
1003  }
1004  }
1005  ( mapData.repeated.begin(), mapData.repeated.end() );
1006 
1007 
1008  // @todo: optimize this!!
1009  // 1: work only on the boundary
1010  // 2: copy back only if necessary
1011  // repeat on actual points to expand overlap
1012  for ( UInt i = 0; i < overlap; i++ )
1013  {
1014  // iterate on points adding all neighbors
1015  for ( std::set<Int>::const_iterator pointIt = addedElementsSet.begin();
1016  pointIt != addedElementsSet.end(); ++pointIt )
1017  {
1018  // iterate on each point neighborhood
1019  for ( neighbors_Type::const_iterator neighborIt = M_pointEdgeNeighborsList[ *pointIt ].begin();
1020  neighborIt != M_pointEdgeNeighborsList[ *pointIt ].end(); ++neighborIt )
1021  {
1022  std::pair<std::set<Int>::iterator, bool> isInserted = myGlobalElementsSet.insert ( *neighborIt );
1023  if ( isInserted.second )
1024  {
1025  typename mesh_Type::EdgeType const& edge = M_fullMesh->edge ( *neighborIt );
1026  for ( UInt edgePoint = 0; edgePoint < mesh_Type::EdgeType::S_numPoints; edgePoint++ )
1027  {
1028  // TODO exclude already included points
1029  // if ( edge.point( edgePoint ).id() != *pointIt )
1030  addedElementsSet.insert ( edge.point ( edgePoint ).id() );
1031  }
1032  }
1033  }
1034  }
1035  }
1036 
1037  mapData.repeated.assign ( myGlobalElementsSet.begin(), myGlobalElementsSet.end() );
1038 
1039  map_Type::mapPtr_Type repeatedMap ( new Epetra_Map ( -1,
1040  mapData.repeated.size(),
1041  &mapData.repeated[0],
1042  0,
1043  *M_comm ) );
1044  ghostMap.setMap ( repeatedMap, Repeated );
1045  }
1046 
1047  return *M_ghostMapOnEdges;
1048 }
1049 
1050 template <typename MeshType>
1051 typename GhostHandler<MeshType>::map_Type& GhostHandler<MeshType>::ghostMapOnElementsFV()
1052 {
1053  // if the map has already been created, return it
1054  if ( M_ghostMapOnElementsFV )
1055  {
1056  return *M_ghostMapOnElementsFV;
1057  }
1058 
1059  if ( M_verbose )
1060  {
1061  std::cout << " GH- ghostMapOnElementsFV()" << std::endl;
1062  }
1063 
1064  // create the map
1065  M_ghostMapOnElementsFV.reset ( new map_Type() );
1066  map_Type& ghostMap ( *M_ghostMapOnElementsFV );
1067 
1068  // use the same Unique map and comm of the original map
1069  ghostMap.setMap ( M_map->map ( Unique ), Unique );
1070  ghostMap.setComm ( M_comm );
1071 
1072  Int* pointer;
1073  std::set<Int> map;
1074 
1075  // get all elements from the repeated map
1076  pointer = M_map->map ( Repeated )->MyGlobalElements();
1077  for ( Int ii = 0; ii < M_map->map ( Repeated )->NumMyElements(); ++ii, ++pointer )
1078  {
1079  map.insert ( *pointer );
1080  }
1081 
1082  // add all facing elements
1083  typedef typename mesh_Type::facet_Type const* facetPtr_Type;
1084  std::vector<facetPtr_Type>
1085  facetsOnSubdInt = M_localMesh->facetList().extractElementsWithFlag (
1086  EntityFlags::SUBDOMAIN_INTERFACE, &Flag::testOneSet );
1087  for ( typename std::vector<facetPtr_Type>::const_iterator facetIt = facetsOnSubdInt.begin();
1088  facetIt != facetsOnSubdInt.end(); ++facetIt )
1089  {
1090  map.insert ( (*facetIt)->secondAdjacentElementIdentity() );
1091  }
1092 
1093  // convert unique list to vector to assure continuity in memorization
1094  std::vector<Int> myGlobalElements ( map.begin(), map.end() );
1095 
1096  // generate map
1097  map_Type::mapPtr_Type repeatedMap ( new Epetra_Map ( -1, myGlobalElements.size(), &myGlobalElements[0], 0, *M_comm ) );
1098  ghostMap.setMap ( repeatedMap, Repeated );
1099 
1100  return *M_ghostMapOnElementsFV;
1101 }
1102 
1103 template <typename MeshType>
1104 typename GhostHandler<MeshType>::map_Type& GhostHandler<MeshType>::ghostMapOnElementsFE ( UInt overlap )
1105 {
1106  // if the map has already been created, return it
1107  if ( M_ghostMapOnElementsFE )
1108  {
1109  return *M_ghostMapOnElementsFE;
1110  }
1111 
1112  if ( M_verbose )
1113  {
1114  std::cout << " GH- ghostMapOnElementsFE()" << std::endl;
1115  }
1116 
1117  // check that the pointElementNeighborsMap has been created
1118  if ( M_pointElementNeighborsList.empty() )
1119  {
1120  if ( M_verbose )
1121  {
1122  std::cerr << "the pointElementNeighborsList is empty, will be generated now" << std::endl;
1123  }
1124  this->createPointElementNeighborsList();
1125  }
1126 
1127  // create the map
1128  M_ghostMapOnElementsFE.reset ( new map_Type() );
1129  map_Type& ghostMap ( *M_ghostMapOnElementsFE );
1130 
1131  // use the same Unique map and comm of the original map
1132  ghostMap.setMap ( M_map->map ( Unique ), Unique );
1133  ghostMap.setComm ( M_comm );
1134 
1135  Int* pointer;
1136  std::set<Int> myGlobalElementsSet;
1137 
1138  // get all elements from the repeated map
1139  pointer = M_map->map ( Repeated )->MyGlobalElements();
1140  for ( Int ii = 0; ii < M_map->map ( Repeated )->NumMyElements(); ++ii, ++pointer )
1141  {
1142  myGlobalElementsSet.insert ( *pointer );
1143  }
1144 
1145  // add all elements with a point on SUBDOMAIN_INTERFACE
1146  typedef typename mesh_Type::point_Type const* pointPtr_Type;
1147  std::vector<pointPtr_Type>
1148  pointsOnSubdInt = M_localMesh->pointList.extractElementsWithFlag (
1149  EntityFlags::SUBDOMAIN_INTERFACE, &Flag::testOneSet );
1150  // must work on global IDs since added elements are not on localMesh
1151  std::vector<ID> pointIDOnSubdInt ( pointsOnSubdInt.size() );
1152  for ( UInt i = 0; i < pointsOnSubdInt.size(); i++)
1153  {
1154  pointIDOnSubdInt[i] = pointsOnSubdInt[i]->id();
1155  }
1156 
1157  std::vector<ID> addedPoints;
1158 
1159  for ( UInt n = 0; n < overlap; n++ )
1160  {
1161  for ( std::vector<ID>::const_iterator globalId = pointIDOnSubdInt.begin();
1162  globalId != pointIDOnSubdInt.end(); ++globalId )
1163  {
1164  // iterate on each point neighborhood
1165  for ( neighbors_Type::const_iterator neighborIt = M_pointElementNeighborsList[ *globalId ].begin();
1166  neighborIt != M_pointElementNeighborsList[ *globalId ].end(); ++neighborIt )
1167  {
1168  std::pair<std::set<Int>::iterator, bool> isInserted = myGlobalElementsSet.insert ( *neighborIt );
1169  if ( isInserted.second )
1170  {
1171  typename mesh_Type::element_Type const& elem = M_fullMesh->element ( *neighborIt );
1172  for ( UInt elemPoint = 0; elemPoint < mesh_Type::element_Type::S_numPoints; elemPoint++ )
1173  {
1174  // TODO exclude already included points
1175  addedPoints.push_back ( elem.point ( elemPoint ).id() );
1176  }
1177  }
1178  }
1179  }
1180  if ( overlap > 1 )
1181  {
1182  pointIDOnSubdInt = addedPoints;
1183  }
1184  }
1185 
1186  // convert unique list to vector to assure continuity in memorization
1187  std::vector<Int> myGlobalElements ( myGlobalElementsSet.begin(), myGlobalElementsSet.end() );
1188 
1189  // generate map
1190  map_Type::mapPtr_Type repeatedMap ( new Epetra_Map ( -1, myGlobalElements.size(), &myGlobalElements[0], 0, *M_comm ) );
1191  ghostMap.setMap ( repeatedMap, Repeated );
1192 
1193  return *M_ghostMapOnElementsFE;
1194 }
1195 
1196 template <typename MeshType>
1197 void GhostHandler<MeshType>::extendGraphFE ( graphPtr_Type elemGraph,
1198  idList_Type const& pointPID,
1199  UInt overlap )
1200 {
1201  if ( M_verbose )
1202  {
1203  std::cout << " GH- ghostMapOnElementsP1( graph )" << std::endl;
1204  }
1205 
1206 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1207  LifeChronoManager<> timeMgr ( M_comm );
1208  LifeChrono timeNL;
1209  timeMgr.add ( "point-element ngbr list", &timeNL );
1210  timeNL.start();
1211 #endif
1212  // check that the pointElementNeighborsMap has been created
1213  if ( M_pointElementNeighborsList.empty() )
1214  {
1215  if ( M_verbose )
1216  {
1217  std::cerr << "the pointElementNeighborsList is empty, will be generated now" << std::endl;
1218  }
1219  this->createPointElementNeighborsList();
1220  }
1221 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1222  timeNL.stop();
1223 #endif
1224 
1225  std::vector<int>& myElems = (*elemGraph) [M_me];
1226 
1227 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1228  // show own elements
1229  M_debugOut << "own elements on proc " << M_me << std::endl;
1230  for ( UInt i = 0; i < myElems.size(); i++ )
1231  {
1232  M_debugOut << myElems[ i ] << std::endl;
1233  }
1234 #endif
1235 
1236 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1237  LifeChrono timePG;
1238  timeMgr.add ( "point graph", &timePG );
1239  timePG.start();
1240 #endif
1241  // generate graph of points
1242  // check: parallel algorithm seems to be faster for this
1243  graph_Type pointGraph ( M_comm->NumProc() );
1244 
1245  std::set<int> localPointsSet;
1246  for ( UInt e = 0; e < (*elemGraph) [ M_me ].size(); e++ )
1247  {
1248  // point block
1249  for ( UInt k = 0; k < mesh_Type::element_Type::S_numPoints; k++ )
1250  {
1251  const ID& pointID = M_fullMesh->element ( (*elemGraph) [ M_me ][ e ] ).point ( k ).id();
1252  localPointsSet.insert ( pointID );
1253  }
1254  }
1255  pointGraph[ M_me ].assign ( localPointsSet.begin(), localPointsSet.end() );
1256 
1257  std::vector<Int> pointGraphSize ( M_comm->NumProc(), -1 );
1258  pointGraphSize[ M_me ] = pointGraph[ M_me ].size();
1259  for ( UInt p = 0; p < static_cast<UInt> ( M_comm->NumProc() ); p++ )
1260  {
1261  M_comm->Broadcast ( &pointGraphSize[ p ], 1, p );
1262  }
1263 
1264  for ( UInt p = 0; p < static_cast<UInt> ( M_comm->NumProc() ); p++ )
1265  {
1266  pointGraph[ p ].resize ( pointGraphSize[ p ] );
1267  }
1268 
1269  // communicate other proc point graphs
1270  for ( UInt p = 0; p < static_cast<UInt> ( M_comm->NumProc() ); p++ )
1271  {
1272  M_comm->Broadcast ( &pointGraph[p][0], pointGraph[p].size(), p );
1273  }
1274 
1275 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1276  timePG.stop();
1277 #endif
1278 
1279  std::vector<int> const& myPoints = pointGraph[ M_me ];
1280 
1281 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1282  M_debugOut << "own points on proc " << M_me << std::endl;
1283  for ( UInt i = 0; i < myPoints.size(); i++ )
1284  {
1285  M_debugOut << myPoints[ i ] << std::endl;
1286  }
1287 #endif
1288 
1289 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1290  LifeChrono timeSI;
1291  timeMgr.add ( "find SUBD_INT", &timeSI );
1292  timeSI.start();
1293 #endif
1294  // initialize a bool vector that tells if an element is in the current partition
1295  std::vector<bool> isInPartition ( M_fullMesh->numElements(), false );
1296  for ( UInt e = 0; e < myElems.size(); e++ )
1297  {
1298  isInPartition[ myElems[ e ] ] = true;
1299  }
1300 
1301  // find subdomain interface points
1302  std::set<Int> mySubdIntPoints;
1303  for ( UInt k = 0; k < myPoints.size(); k++ )
1304  {
1305  int const& currentPoint = myPoints[ k ];
1306  // mark as SUBD_INT point only if the point is owned by current process
1307  if ( pointPID[ currentPoint ] == static_cast<Int>(M_me) )
1308  {
1309  // check if all element neighbors are on this proc
1310  for ( neighbors_Type::const_iterator neighborIt = M_pointElementNeighborsList[ currentPoint ].begin();
1311  neighborIt != M_pointElementNeighborsList[ currentPoint ].end(); ++neighborIt )
1312  {
1313  // add the point if a neighbor is missing
1314  if ( !isInPartition[ *neighborIt ] )
1315  {
1316  mySubdIntPoints.insert ( currentPoint );
1317  break;
1318  }
1319  }
1320  }
1321  }
1322 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1323  timeSI.stop();
1324 #endif
1325 
1326 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1327  M_debugOut << "own SUBDOMAIN_INTERFACE points on proc " << M_me << std::endl;
1328  for ( std::set<Int>::const_iterator i = mySubdIntPoints.begin(); i != mySubdIntPoints.end(); ++i )
1329  {
1330  M_debugOut << *i << std::endl;
1331  }
1332 #endif
1333 
1334 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1335  LifeChrono timeOP;
1336  timeMgr.add ( "overlapping points", &timeOP );
1337  timeOP.start();
1338 #endif
1339 
1340  std::vector<int> workingPoints ( mySubdIntPoints.begin(), mySubdIntPoints.end() );
1341  std::set<int> newPoints;
1342  std::set<int> augmentedElemsSet ( myElems.begin(), myElems.end() );
1343 
1344  for ( UInt o = 0; o < overlap; o++ )
1345  {
1346 
1347 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1348  M_debugOut << "workingPoints" << std::endl;
1349  for ( UInt i = 0; i < workingPoints.size(); i++ )
1350  {
1351  M_debugOut << workingPoints[ i ] << std::endl;
1352  }
1353 #endif
1354  for ( UInt k = 0; k < workingPoints.size(); k++ )
1355  {
1356  const int& currentPoint = workingPoints[ k ];
1357  // iterate on point neighborhood
1358  for ( neighbors_Type::const_iterator neighborIt = M_pointElementNeighborsList[ currentPoint ].begin();
1359  neighborIt != M_pointElementNeighborsList[ currentPoint ].end(); ++neighborIt )
1360  {
1361  std::pair<std::set<Int>::iterator, bool> isInserted = augmentedElemsSet.insert ( *neighborIt );
1362  if ( isInserted.second )
1363  {
1364  // if the element is inserted in the list, we add its points to the ones
1365  // to be checked for next overlap value
1366  for ( UInt j = 0; j < mesh_Type::element_Type::S_numPoints; j++ )
1367  {
1368  newPoints.insert ( M_fullMesh->element ( *neighborIt ).point ( j ).id() );
1369  }
1370  }
1371  }
1372  }
1373 
1374 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1375  M_debugOut << "augmentedElemsSet" << std::endl;
1376  for ( std::set<Int>::const_iterator i = augmentedElemsSet.begin(); i != augmentedElemsSet.end(); ++i )
1377  {
1378  M_debugOut << *i << std::endl;
1379  }
1380 #endif
1381  // clean up newPoints from already analized points
1382  for ( UInt k = 0; k < workingPoints.size(); k++ )
1383  {
1384  newPoints.erase ( newPoints.find ( workingPoints[ k ] ) );
1385  }
1386 
1387 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1388  M_debugOut << "newPoints" << std::endl;
1389  for ( std::set<int>::const_iterator i = newPoints.begin(); i != newPoints.end(); ++i )
1390  {
1391  M_debugOut << *i << std::endl;
1392  }
1393 #endif
1394  // set up workingPoints if we are not exiting
1395  if ( o + 1 < overlap )
1396  {
1397  workingPoints.assign ( newPoints.begin(), newPoints.end() );
1398  }
1399  }
1400 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1401  timeOP.stop();
1402 #endif
1403 
1404  // assign the augmentedElems to the element graph
1405  myElems.assign ( augmentedElemsSet.begin(), augmentedElemsSet.end() );
1406 
1407 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1408  timeMgr.print();
1409 #endif
1410 }
1411 
1412 template <typename MeshType>
1413 void GhostHandler<MeshType>::extendGraphFE ( const vertexPartitionPtr_Type& elemGraph,
1414  idList_Type const& pointPID,
1415  UInt overlap,
1416  UInt partIndex)
1417 {
1418  if ( M_verbose )
1419  {
1420  std::cout << " GH- ghostMapOnElementsP1( graph )" << std::endl;
1421  }
1422 
1423 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1424  LifeChronoManager<> timeMgr ( M_comm );
1425  LifeChrono timeNL;
1426  timeMgr.add ( "node-element ngbr list", &timeNL );
1427  timeNL.start();
1428 #endif
1429  // check that the pointElementNeighborsMap has been created
1430  if ( M_pointElementNeighborsList.empty() )
1431  {
1432  if ( M_verbose )
1433  {
1434  std::cerr << "the pointElementNeighborsList is empty, will be generated now" << std::endl;
1435  }
1436  this->createPointElementNeighborsList();
1437  }
1438 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1439  timeNL.stop();
1440 #endif
1441 
1442  std::vector<int>& myElems = * (elemGraph->at (partIndex) );
1443 
1444 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1445  // show own elements
1446  M_debugOut << "own elements on proc " << partIndex << std::endl;
1447  for ( UInt i = 0; i < myElems.size(); i++ )
1448  {
1449  M_debugOut << myElems[ i ] << std::endl;
1450  }
1451 #endif
1452 
1453 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1454  LifeChrono timePG;
1455  timeMgr.add ( "point graph", &timePG );
1456  timePG.start();
1457 #endif
1458  // generate graph of points
1459  // check: parallel algorithm seems to be faster for this
1460  Int numParts = elemGraph->size();
1461  graph_Type pointGraph ( numParts );
1462 
1463  std::set<int> localPointsSet;
1464  for ( UInt e = 0; e < elemGraph->at (partIndex)->size(); e++ )
1465  {
1466  // point block
1467  for ( UInt k = 0; k < mesh_Type::element_Type::S_numPoints; k++ )
1468  {
1469  const ID& pointID = M_fullMesh->element ( elemGraph->at (partIndex)->at (e) ).point ( k ).id();
1470  localPointsSet.insert ( pointID );
1471  }
1472  }
1473  pointGraph[ partIndex ].assign ( localPointsSet.begin(), localPointsSet.end() );
1474 
1475  std::vector<Int> pointGraphSize ( numParts, -1 );
1476  pointGraphSize[ partIndex ] = pointGraph[ partIndex ].size();
1477  if (M_comm->NumProc() > 1)
1478  {
1479  for ( UInt p = 0; p < static_cast<UInt> ( M_comm->NumProc() ); p++ )
1480  {
1481  M_comm->Broadcast ( &pointGraphSize[ p ], 1, p );
1482  }
1483 
1484  for ( UInt p = 0; p < static_cast<UInt> ( M_comm->NumProc() ); p++ )
1485  {
1486  pointGraph[ p ].resize ( pointGraphSize[ p ] );
1487  }
1488 
1489  // communicate other proc point graphs
1490  for ( UInt p = 0; p < static_cast<UInt> ( M_comm->NumProc() ); p++ )
1491  {
1492  M_comm->Broadcast ( &pointGraph[p][0], pointGraph[p].size(), p );
1493  }
1494  }
1495 
1496 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1497  timePG.stop();
1498 #endif
1499 
1500  std::vector<int> const& myPoints = pointGraph[ partIndex ];
1501 
1502 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1503  M_debugOut << "own points on proc " << partIndex << std::endl;
1504  for ( UInt i = 0; i < myPoints.size(); i++ )
1505  {
1506  M_debugOut << myPoints[ i ] << std::endl;
1507  }
1508 #endif
1509 
1510 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1511  LifeChrono timeSI;
1512  timeMgr.add ( "find SUBD_INT", &timeSI );
1513  timeSI.start();
1514 #endif
1515  // initialize a bool vector that tells if an element is in the current partition
1516  std::vector<bool> isInPartition ( M_fullMesh->numElements(), false );
1517  for ( UInt e = 0; e < myElems.size(); e++ )
1518  {
1519  isInPartition[ myElems[ e ] ] = true;
1520  }
1521 
1522  // find subdomain interface points
1523  std::set<Int> mySubdIntPoints;
1524  for ( UInt k = 0; k < myPoints.size(); k++ )
1525  {
1526  int const& currentPoint = myPoints[ k ];
1527  // mark as SUBD_INT point only if the point is owned by current process
1528  if ( pointPID[ currentPoint ] == static_cast<Int>(partIndex) )
1529  {
1530  // check if all element neighbors are on this proc
1531  for ( neighbors_Type::const_iterator neighborIt = M_pointElementNeighborsList[ currentPoint ].begin();
1532  neighborIt != M_pointElementNeighborsList[ currentPoint ].end(); ++neighborIt )
1533  {
1534  // add the point if a neighbor is missing
1535  if ( !isInPartition[ *neighborIt ] )
1536  {
1537  mySubdIntPoints.insert ( currentPoint );
1538  break;
1539  }
1540  }
1541  }
1542  }
1543 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1544  timeSI.stop();
1545 #endif
1546 
1547 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1548  M_debugOut << "own SUBDOMAIN_INTERFACE points on proc " << partIndex << std::endl;
1549  for ( std::set<Int>::const_iterator i = mySubdIntPoints.begin(); i != mySubdIntPoints.end(); ++i )
1550  {
1551  M_debugOut << *i << std::endl;
1552  }
1553 #endif
1554 
1555 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1556  LifeChrono timeOP;
1557  timeMgr.add ( "overlapping points", &timeOP );
1558  timeOP.start();
1559 #endif
1560 
1561  std::vector<int> workingPoints ( mySubdIntPoints.begin(), mySubdIntPoints.end() );
1562  std::set<int> newPoints;
1563  std::set<int> augmentedElemsSet ( myElems.begin(), myElems.end() );
1564 
1565  for ( UInt o = 0; o < overlap; o++ )
1566  {
1567 
1568 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1569  M_debugOut << "workingPoints" << std::endl;
1570  for ( UInt i = 0; i < workingPoints.size(); i++ )
1571  {
1572  M_debugOut << workingPoints[ i ] << std::endl;
1573  }
1574 #endif
1575  for ( UInt k = 0; k < workingPoints.size(); k++ )
1576  {
1577  const int& currentPoint = workingPoints[ k ];
1578  // iterate on point neighborhood
1579  for ( neighbors_Type::const_iterator neighborIt = M_pointElementNeighborsList[ currentPoint ].begin();
1580  neighborIt != M_pointElementNeighborsList[ currentPoint ].end(); ++neighborIt )
1581  {
1582  std::pair<std::set<Int>::iterator, bool> isInserted = augmentedElemsSet.insert ( *neighborIt );
1583  if ( isInserted.second )
1584  {
1585  // if the element is inserted in the list, we add its points to the ones
1586  // to be checked for next overlap value
1587  for ( UInt j = 0; j < mesh_Type::element_Type::S_numPoints; j++ )
1588  {
1589  newPoints.insert ( M_fullMesh->element ( *neighborIt ).point ( j ).id() );
1590  }
1591  }
1592  }
1593  }
1594 
1595 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1596  M_debugOut << "augmentedElemsSet" << std::endl;
1597  for ( std::set<Int>::const_iterator i = augmentedElemsSet.begin(); i != augmentedElemsSet.end(); ++i )
1598  {
1599  M_debugOut << *i << std::endl;
1600  }
1601 #endif
1602  // clean up newPoints from already analized points
1603  for ( UInt k = 0; k < workingPoints.size(); k++ )
1604  {
1605  newPoints.erase ( newPoints.find ( workingPoints[ k ] ) );
1606  }
1607 
1608 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1609  M_debugOut << "newPoints" << std::endl;
1610  for ( std::set<int>::const_iterator i = newPoints.begin(); i != newPoints.end(); ++i )
1611  {
1612  M_debugOut << *i << std::endl;
1613  }
1614 #endif
1615  // set up workingPoints if we are not exiting
1616  if ( o + 1 < overlap )
1617  {
1618  workingPoints.assign ( newPoints.begin(), newPoints.end() );
1619  }
1620  }
1621 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1622  timeOP.stop();
1623 #endif
1624 
1625  // assign the augmentedElems to the element graph
1626  myElems.assign ( augmentedElemsSet.begin(), augmentedElemsSet.end() );
1627 
1628 #ifdef LIFEV_GHOSTHANDLER_DEBUG
1629  timeMgr.print();
1630 #endif
1631 }
1632 
1633 template <typename MeshType>
1634 void GhostHandler<MeshType>::showMe ( bool const /*verbose*/, std::ostream& out )
1635 {
1636  out << "GhostHandler::showMe()" << std::endl;
1637  out << "M_pointPointNeighborsMap" << std::endl;
1638  for ( UInt i = 0; i < M_pointPointNeighborsList.size(); i++ )
1639  {
1640  out << i << " > ";
1641  for ( neighbors_Type::const_iterator nIt = M_pointPointNeighborsList[ i ].begin();
1642  nIt != M_pointPointNeighborsList[ i ].end(); ++nIt )
1643  {
1644  out << *nIt << " ";
1645  }
1646  out << std::endl;
1647  }
1648  out << "M_pointElementNeighborsMap" << std::endl;
1649  for ( UInt i = 0; i < M_pointPointNeighborsList.size(); i++ )
1650  {
1651  out << i << " > ";
1652  for ( neighbors_Type::const_iterator nIt = M_pointPointNeighborsList[ i ].begin();
1653  nIt != M_pointPointNeighborsList[ i ].end(); ++nIt )
1654  {
1655  out << *nIt << " ";
1656  }
1657  out << std::endl;
1658  }
1659 }
1660 
1661 
1662 }
1663 
1664 #endif /* _GHOSTHANDLER_HPP_ */
GhostHandler(meshPtr_Type fullMesh, commPtr_Type const &comm)
Constructor.
~GhostHandler()
Destructor.
void clean(NeighborType const neighborType=ALL_NEIGHBORS)
Clean up neighbor lists.
mapPtr_Type M_ghostMapOnElementsFV
std::vector< markerID_Type > markerIDList_Type
neighborList_Type M_pointEdgeNeighborsList
std::vector< Int > idList_Type
GhostHandler(meshPtr_Type fullMesh, meshPtr_Type localMesh, mapPtr_Type map, commPtr_Type const &comm)
Constructor.
NeighborType const RIDGE_NEIGHBORS
neighborList_Type const & pointElementNeighborsList()
List of element neighbors to a point (identified by the global ID)
commPtr_Type const M_comm
std::shared_ptr< comm_Type > commPtr_Type
neighbors_Type neighborsWithinRadius(UInt globalID, Real radius)
Create neighbors to a given point within a specified radius.
std::bitset< 4 > NeighborType
meshPtr_Type M_localMesh
mapPtr_Type M_ghostMapOnElementsFE
void extendGraphFE(graphPtr_Type elemGraph, idList_Type const &pointPID, UInt overlap)
Extend the subdomains graph of the given overlap.
NeighborType const POINT_NEIGHBORS
neighborList_Type M_pointPointNeighborsList
void createPointEdgeNeighborsList()
Create the list of edge neighbors to the points.
std::shared_ptr< mesh_Type > meshPtr_Type
void setVerbose(const bool &verbose)
Set verbosity.
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
ID markerID_Type
markerID_Type is the type used to store the geometric entity marker IDs
Definition: Marker.hpp:81
mapPtr_Type M_ghostMapOnPoints
void updateInverseJacobian(const UInt &iQuadPt)
void setMap(mapPtr_Type map, MapEpetraType mapType)
set the internal Epetra_Maps
Definition: MapEpetra.cpp:414
void createPointNeighbors()
Create point neighbors to points and store them in the NeighborMarker.
void release()
Release pointers to full and local mesh.
std::vector< idList_Type > graph_Type
map_Type & ghostMapOnElementsFE(UInt overlap)
Create an overlapped map on elements for Finite Elements.
NeighborType const ALL_NEIGHBORS
neighbors_Type circleNeighbors(UInt globalID, UInt nCircles=1)
Create neighbors to a given point, with a specified number of generations.
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
void createPointPointNeighborsList(markerIDListSigned_Type const &flags)
Create the list of point neighbors to points that are in the given list of MarkerIDs.
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
std::shared_ptr< idList_Type > idListPtr_Type
NeighborType const FACET_NEIGHBORS
std::vector< int > markerIDListSigned_Type
std::shared_ptr< graph_Type > graphPtr_Type
bool isInside(markerID_Type const &pointMarker, std::vector< int > const &markerIDList)
mesh_Type const & localMesh()
Local mesh getter.
std::shared_ptr< map_Type > mapPtr_Type
Definition: MapEpetra.hpp:80
map_Type const & map()
Standard map getter.
std::shared_ptr< map_Type > mapPtr_Type
void setUpNeighbors(NeighborType const neighborType=ALL_NEIGHBORS)
Initialize neighbors list.
MapEpetraData.
neighborList_Type const & pointPointNeighborsList()
List of point neighbors to a point (identified by the global ID)
double Real
Generic real data.
Definition: LifeV.hpp:175
neighborList_Type const & pointEdgeNeighborsList()
List of edge neighbors to a point (identified by the global ID)
GhostHandler(commPtr_Type const &comm)
Constructor.
mesh_Type const & fullMesh()
Full mesh getter.
std::unordered_set< ID > neighbors_Type
void createPointElementNeighborsList()
Create the list of element neighbors to the points.
Epetra_Comm comm_Type
map_Type & ghostMapOnPoints(UInt overlap)
Create an overlapped map on points.
std::shared_ptr< vertexPartition_Type > vertexPartitionPtr_Type
void extendGraphFE(const vertexPartitionPtr_Type &elemGraph, idList_Type const &pointPID, UInt overlap, UInt partIndex)
Extend the subdomains graph of the given overlap.
map_Type & ghostMapOnEdges(UInt overlap)
Create an overlapped map on edges.
mapPtr_Type const M_map
void setComm(commPtr_Type const &commPtr)
Set the communicator.
Definition: MapEpetra.cpp:407
void showMe(bool const verbose=false, std::ostream &out=std::cout)
showMe method
void createPointPointNeighborsList()
Create the list of point neighbors to points.
mapPtr_Type M_ghostMapOnEdges
map_Type & ghostMapOnPoints()
Create an overlapped map on points.
meshPtr_Type M_fullMesh
std::vector< neighbors_Type > neighborList_Type
void importFromHDF5(std::string const &fileName="ghostmap")
Import neighbor lists to an hdf5 file.
NeighborType const ELEMENT_NEIGHBORS
neighborList_Type M_pointElementNeighborsList
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
std::vector< idListPtr_Type > vertexPartition_Type
map_Type & ghostMapOnElementsFV()
Create an overlapped map on elements for Finite Volumes.