dune-fem  2.4.1-rc
threadpartitioner.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_THREADPARTITIONER_HH
2 #define DUNE_FEM_THREADPARTITIONER_HH
3 
4 //- system includes
5 #include <string>
6 #include <list>
7 #include <map>
8 #include <vector>
9 
10 #include <dune/common/parallel/mpihelper.hh>
12 
13 #if HAVE_DUNE_ALUGRID
14 #include <dune/alugrid/3d/alugrid.hh>
15 
16 #warning "Using the ThreadPartitioner"
17 
18 namespace Dune {
19 
20 template < class GridPartImp >
21 class ThreadPartitioner
22 {
23 
24 protected:
25  typedef GridPartImp GridPartType;
26  typedef typename GridPartType :: GridType GridType;
27  typedef typename GridType :: Traits :: LocalIdSet LocalIdSetType;
28  typedef typename LocalIdSetType :: IdType IdType;
29 
30  typedef typename GridPartType :: IndexSetType IndexSetType;
31  typedef typename IndexSetType :: IndexType IndexType;
32 
33 protected:
34  typedef ALU3DSPACE LoadBalancer LoadBalancerType;
35  typedef typename LoadBalancerType :: DataBase DataBaseType;
36 
37  // type of communicator interface
38  typedef ALU3DSPACE MpAccessLocal MPAccessInterfaceType;
39 
40  // type of communicator implementation
41  typedef ALU3DSPACE MpAccessSerial MPAccessImplType;
42 
43  mutable MPAccessImplType mpAccess_;
44 
45  DataBaseType db_;
46 
47  const GridPartType& gridPart_;
48  const IndexSetType& indexSet_;
49 
50  typedef typename GridPartType :: template Codim<0> :: EntityType EntityType;
51 
52  // load balancer bounds
53  const double ldbOver_ ;
54  const double ldbUnder_;
55  const double cutOffFactor_;
56 
57  const int pSize_ ;
58  int graphSize_;
59 
60  std::vector< int > index_;
61  int indexCounter_ ;
62 
63  std::vector< int > partition_;
64 
65 public:
66  enum Method { recursive = 0, // METIS_PartGraphRecursive,
67  kway = 1, // METIS_PartGraphKway
68  sfc = 2 // ALUGRID_SpaceFillingCurve
69  };
70 
75  ThreadPartitioner( const GridPartType& gridPart,
76  const int pSize,
77  const double cutOffFactor = 1.0 )
78  : mpAccess_(),
79  db_ (),
80  gridPart_( gridPart )
81  , indexSet_( gridPart_.indexSet() )
82  , ldbOver_(1.2)
83  , ldbUnder_(0.0)
84  , cutOffFactor_( std::max( double(1.0 - cutOffFactor), 0.0 ) )
85  , pSize_( pSize )
86  , graphSize_( pSize_ )
87  , index_( indexSet_.size( 0 ), -1 )
88  , indexCounter_( 0 )
89  {
90  calculateGraph( gridPart_ );
91  }
92 
93 protected:
97  int getIndex( const size_t idx )
98  {
99  assert( idx < index_.size() );
100  if( index_[ idx ] < 0 ) index_[ idx ] = indexCounter_ ++ ;
101  return index_[ idx ] ;
102  }
103 
105  int getIndex( const size_t idx ) const
106  {
107  assert( idx < index_.size() );
108  return index_[ idx ] ;
109  }
110 
112  int getIndex( const EntityType& entity )
113  {
114  return getIndex( indexSet_.index( entity ) );
115  }
116 
118  int getIndex( const EntityType& entity ) const
119  {
120  return getIndex( indexSet_.index( entity ) );
121  }
122 
123  void calculateGraph( const GridPartType& gridPart )
124  {
125  graphSize_ = 0;
126  typedef typename GridPartType :: template Codim< 0 > :: IteratorType Iterator;
127  const Iterator end = gridPart.template end<0> ();
128  const int cutOff = cutOffFactor_ * (indexSet_.size( 0 ) / pSize_) ;
129  // create graph
130  for(Iterator it = gridPart.template begin<0> (); it != end; ++it )
131  {
132  const EntityType& entity = *it;
133  assert( entity.partitionType() == InteriorEntity );
134  ldbUpdateVertex ( entity, cutOff,
135  gridPart.ibegin( entity ),
136  gridPart.iend( entity ),
137  db_ );
138  }
139  }
140 
141  template <class IntersectionIteratorType>
142  void ldbUpdateVertex ( const EntityType & entity,
143  const int cutOff,
144  const IntersectionIteratorType& ibegin,
145  const IntersectionIteratorType& iend,
146  DataBaseType & db )
147  {
148  const int index = getIndex( entity );
149  int weight = (index >= cutOff) ? 1 : 8; // a least weight 1 for macro element
150 
151  {
153  {
154  // calculate weight, which is number of children
155  const int mxl = gridPart_.grid().maxLevel();
156  if( mxl > entity.level() && ! entity.isLeaf() )
157  {
158  typedef typename EntityType :: HierarchicIterator HierIt;
159  const HierIt endit = entity.hend( mxl );
160  for(HierIt it = entity.hbegin( mxl ); it != endit; ++it)
161  ++weight;
162  }
163  }
164 
165  db.vertexUpdate( typename LoadBalancerType::GraphVertex( index, weight ) );
166  ++graphSize_;
167  }
168 
169  // set weight for faces (to be revised)
170  updateFaces( entity, ibegin, iend, weight, db );
171  }
172 
173  template <class IntersectionIteratorType>
174  void updateFaces(const EntityType& en,
175  IntersectionIteratorType nit,
176  const IntersectionIteratorType endit,
177  const int weight,
178  DataBaseType & db)
179  {
180  for( ; nit != endit; ++nit )
181  {
182  typedef typename IntersectionIteratorType :: Intersection IntersectionType;
183  const IntersectionType& intersection = *nit;
184  if(intersection.neighbor())
185  {
186  EntityType nb = intersection.outside();
187  if( nb.partitionType() == InteriorEntity )
188  {
189  const int eid = getIndex( en );
190  const int nid = getIndex( nb );
191  // the newest ALU version only needs the edges to be inserted only once
192  if( eid < nid )
193  // the older version works with double insertion
194  // insert edges twice, with both orientations
195  // the ALUGrid partitioner expects it this way
196  {
197  typedef typename LoadBalancerType :: GraphEdge GraphEdge;
198  db.edgeUpdate ( GraphEdge ( eid, nid, weight, -1, -1 ) );
199  }
200  }
201  }
202  }
203  }
204 
205 public:
212  bool serialPartition( const Method method = recursive )
213  {
214  if( pSize_ > 1 )
215  {
216  // if the graph size is smaller then the number of partitions
217  // the distribution is easy to compute
218  if( graphSize_ <= pSize_ )
219  {
220  partition_.resize( graphSize_ );
221  for( int i=0; i<graphSize_; ++ i )
222  partition_[ i ] = i;
223  }
224  else
225  {
226  // || HAVE_METIS
227  if( method == recursive )
228  partition_ = db_.repartition( mpAccess_, DataBaseType :: METIS_PartGraphRecursive, pSize_ );
229  else if( method == kway )
230  partition_ = db_.repartition( mpAccess_, DataBaseType :: METIS_PartGraphKway, pSize_ );
231  else if( method == sfc )
232  {
233  partition_ = db_.repartition( mpAccess_, DataBaseType :: ALUGRID_SpaceFillingCurveSerial, pSize_ );
234  }
235  else
236  DUNE_THROW(InvalidStateException,"ThreadPartitioner::serialPartition: wrong method");
237  assert( int(partition_.size()) >= graphSize_ );
238  }
239 
240  /*
241  assert( partition_.size() > 0 );
242  std::vector< int > counter( pSize_ , 0 );
243  for( size_t i =0; i<partition_.size(); ++i)
244  {
245  std::cout << "part[" << i << "] = " << partition_[ i ] << endl;
246  ++counter[ partition_[ i ] ];
247  }
248  */
249  return partition_.size() > 0;
250  }
251  else
252  {
253  partition_.resize( indexSet_.size( 0 ) );
254  for( size_t i =0; i<partition_.size(); ++i )
255  partition_[ i ] = 0;
256  return false ;
257  }
258  }
259 
260  std::set < int, std::less < int > > scan() const
261  {
262  return db_.scan();
263  }
264 
265  int getRank( const EntityType& entity ) const
266  {
267  //std::cout << "partSize = " << partition_.size() << " idx = " << getIndex( entity ) << std::endl;
268  assert( (int) partition_.size() > getIndex( entity ) );
269  return partition_[ getIndex( entity ) ];
270  }
271 
272  bool validEntity( const EntityType& entity, const int rank ) const
273  {
274  return getRank( entity ) == rank;
275  }
276 
277 };
278 
279 } // end namespace Dune
280 
281 #else
282 #warning "DUNE-ALUGrid Partitioner not available"
283 #endif // HAVE_DUNE_ALUGRID
284 
285 #endif // ifndef DUNE_FEM_THREADPARTITIONER_HH
static constexpr T max(T a)
Definition: utility.hh:65
static const bool v
Definition: gridpart/common/capabilities.hh:19
Definition: coordinate.hh:4
STL namespace.