DUNE-FEM (unstable)

threadpartitioner.hh
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
11#include <dune/fem/gridpart/common/capabilities.hh>
12
13#if HAVE_DUNE_ALUGRID
14#include <dune/alugrid/3d/alugrid.hh>
15
16//#warning "Using the ThreadPartitioner"
17
18namespace Dune {
19
20template < class GridPartImp >
21class ThreadPartitioner
22{
23
24protected:
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
33protected:
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
65public:
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
93protected:
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 {
152 if( Fem::GridPartCapabilities::hasGrid< GridPartType >::v )
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
205public:
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
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
@ InteriorEntity
all interior entities
Definition: gridenums.hh:31
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
Helpers for dealing with MPI.
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)