00001
00002 #ifndef DUNE_AMG_INDICESCOARSENER_HH
00003 #define DUNE_AMG_INDICESCOARSENER_HH
00004
00005 #include<dune/istl/indicessyncer.hh>
00006 #include<vector>
00007 #include"renumberer.hh"
00008
00009 #if HAVE_MPI
00010 #include<dune/istl/owneroverlapcopy.hh>
00011 #endif
00012
00013 #include"pinfo.hh"
00014
00015 namespace Dune
00016 {
00017 namespace Amg
00018 {
00019
00031 template<typename T, typename E>
00032 class IndicesCoarsener
00033 {
00034 };
00035
00036
00037 #if HAVE_MPI
00038
00039 template<typename T, typename E>
00040 class ParallelIndicesCoarsener
00041 {
00042 public:
00046 typedef E ExcludedAttributes;
00047
00051 typedef T ParallelInformation;
00052
00053 typedef typename ParallelInformation::ParallelIndexSet ParallelIndexSet;
00054
00058 typedef typename ParallelIndexSet::GlobalIndex GlobalIndex;
00059
00063 typedef typename ParallelIndexSet::LocalIndex LocalIndex;
00064
00068 typedef typename LocalIndex::Attribute Attribute;
00069
00073 typedef Dune::RemoteIndices<ParallelIndexSet> RemoteIndices;
00074
00086 template<typename Graph, typename VM>
00087 static typename Graph::VertexDescriptor
00088 coarsen(ParallelInformation& fineInfo,
00089 Graph& fineGraph,
00090 VM& visitedMap,
00091 AggregatesMap<typename Graph::VertexDescriptor>& aggregates,
00092 ParallelInformation& coarseInfo);
00093
00094 private:
00095 template<typename G, typename I>
00096 class ParallelAggregateRenumberer: public AggregateRenumberer<G>
00097 {
00098 typedef typename G::VertexDescriptor Vertex;
00099
00100 typedef I GlobalLookupIndexSet;
00101
00102 typedef typename GlobalLookupIndexSet::IndexPair IndexPair;
00103
00104 typedef typename IndexPair::GlobalIndex GlobalIndex;
00105
00106 public:
00107 ParallelAggregateRenumberer(AggregatesMap<Vertex>& aggregates, const I& lookup)
00108 : AggregateRenumberer<G>(aggregates), isPublic_(false), lookup_(lookup),
00109 globalIndex_(std::numeric_limits<GlobalIndex>::max())
00110 {}
00111
00112
00113 void operator()(const typename G::ConstEdgeIterator& edge)
00114 {
00115 AggregateRenumberer<G>::operator()(edge);
00116 const IndexPair* pair= lookup_.pair(edge.target());
00117 if(pair!=0){
00118 globalIndex(pair->global());
00119 attribute(pair->local().attribute());
00120 isPublic(pair->local().isPublic());
00121 }
00122 }
00123
00124 Vertex operator()(const GlobalIndex& global)
00125 {
00126 Vertex current = this->number_;
00127 this->operator++();
00128 return current;
00129 }
00130
00131 bool isPublic()
00132 {
00133 return isPublic_;
00134 }
00135
00136 void isPublic(bool b)
00137 {
00138 isPublic_ = isPublic_ || b;
00139 }
00140
00141 void reset()
00142 {
00143 globalIndex_ = std::numeric_limits<GlobalIndex>::max();
00144 isPublic_=false;
00145 }
00146
00147 void attribute(const Attribute& attribute)
00148 {
00149 attribute_=attribute;
00150 }
00151
00152 Attribute attribute()
00153 {
00154 return attribute_;
00155 }
00156
00157 const GlobalIndex& globalIndex() const
00158 {
00159 return globalIndex_;
00160 }
00161
00162 void globalIndex(const GlobalIndex& global)
00163 {
00164 globalIndex_ = global;
00165 }
00166
00167 private:
00168 bool isPublic_;
00169 Attribute attribute_;
00170 const GlobalLookupIndexSet& lookup_;
00171 GlobalIndex globalIndex_;
00172 };
00173
00174 template<typename Graph, typename VM, typename I>
00175 static void buildCoarseIndexSet(const ParallelInformation& pinfo,
00176 Graph& fineGraph,
00177 VM& visitedMap,
00178 AggregatesMap<typename Graph::VertexDescriptor>& aggregates,
00179 ParallelIndexSet& coarseIndices,
00180 ParallelAggregateRenumberer<Graph,I>& renumberer);
00181
00182 template<typename Graph,typename I>
00183 static void buildCoarseRemoteIndices(const RemoteIndices& fineRemote,
00184 const AggregatesMap<typename Graph::VertexDescriptor>& aggregates,
00185 ParallelIndexSet& coarseIndices,
00186 RemoteIndices& coarseRemote,
00187 ParallelAggregateRenumberer<Graph,I>& renumberer);
00188
00189 };
00190
00194 template<typename G, typename L, typename E>
00195 class IndicesCoarsener<OwnerOverlapCopyCommunication<G,L>,E>
00196 : public ParallelIndicesCoarsener<OwnerOverlapCopyCommunication<G,L>,E>
00197 {};
00198
00199
00200 #endif
00201
00208 template<typename E>
00209 class IndicesCoarsener<SequentialInformation,E>
00210 {
00211 public:
00212 template<typename Graph, typename VM>
00213 static typename Graph::VertexDescriptor
00214 coarsen(const SequentialInformation& fineInfo,
00215 Graph& fineGraph,
00216 VM& visitedMap,
00217 AggregatesMap<typename Graph::VertexDescriptor>& aggregates,
00218 SequentialInformation& coarseInfo);
00219 };
00220
00221 #if HAVE_MPI
00222 template<typename T, typename E>
00223 template<typename Graph, typename VM>
00224 inline typename Graph::VertexDescriptor
00225 ParallelIndicesCoarsener<T,E>::coarsen(ParallelInformation& fineInfo,
00226 Graph& fineGraph,
00227 VM& visitedMap,
00228 AggregatesMap<typename Graph::VertexDescriptor>& aggregates,
00229 ParallelInformation& coarseInfo)
00230 {
00231 ParallelAggregateRenumberer<Graph,typename ParallelInformation::GlobalLookupIndexSet> renumberer(aggregates, fineInfo.globalLookup());
00232 buildCoarseIndexSet(fineInfo, fineGraph, visitedMap, aggregates,
00233 coarseInfo.indexSet(), renumberer);
00234 buildCoarseRemoteIndices(fineInfo.remoteIndices(), aggregates, coarseInfo.indexSet(),
00235 coarseInfo.remoteIndices(), renumberer);
00236
00237 return renumberer;
00238 }
00239
00240 template<typename T, typename E>
00241 template<typename Graph, typename VM, typename I>
00242 void ParallelIndicesCoarsener<T,E>::buildCoarseIndexSet(const ParallelInformation& pinfo,
00243 Graph& fineGraph,
00244 VM& visitedMap,
00245 AggregatesMap<typename Graph::VertexDescriptor>& aggregates,
00246 ParallelIndexSet& coarseIndices,
00247 ParallelAggregateRenumberer<Graph,I>& renumberer)
00248 {
00249 typedef typename Graph::VertexDescriptor Vertex;
00250 typedef typename Graph::ConstVertexIterator Iterator;
00251 typedef typename ParallelInformation::GlobalLookupIndexSet GlobalLookupIndexSet;
00252
00253 Iterator end = fineGraph.end();
00254 const GlobalLookupIndexSet& lookup = pinfo.globalLookup();
00255
00256 coarseIndices.beginResize();
00257
00258
00259
00260
00261 for(Iterator index = fineGraph.begin(); index != end; ++index){
00262 if(aggregates[*index]!=AggregatesMap<typename Graph::VertexDescriptor>::ISOLATED)
00263 if(!get(visitedMap, *index)){
00264
00265 typedef typename GlobalLookupIndexSet::IndexPair IndexPair;
00266 const IndexPair* pair= lookup.pair(*index);
00267
00268 renumberer.reset();
00269 if(pair!=0 && !ExcludedAttributes::contains(pair->local().attribute())){
00270 renumberer.attribute(pair->local().attribute());
00271 renumberer.isPublic(pair->local().isPublic());
00272 renumberer.globalIndex(pair->global());
00273 }
00274
00275
00276 aggregates.template breadthFirstSearch<false>(*index, aggregates[*index],
00277 fineGraph, renumberer, visitedMap);
00278
00279 typedef typename GlobalLookupIndexSet::IndexPair::GlobalIndex GlobalIndex;
00280
00281 if(renumberer.globalIndex()!=std::numeric_limits<GlobalIndex>::max()){
00282
00283 coarseIndices.add(renumberer.globalIndex(),
00284 LocalIndex(renumberer, renumberer.attribute(),
00285 renumberer.isPublic()));
00286 }
00287
00288 aggregates[*index] = renumberer;
00289 ++renumberer;
00290 }
00291 }
00292
00293 coarseIndices.endResize();
00294
00295 assert(static_cast<std::size_t>(renumberer) >= coarseIndices.size());
00296
00297
00298 for(Iterator vertex=fineGraph.begin(); vertex != end; ++vertex)
00299 put(visitedMap, *vertex, false);
00300 }
00301
00302 template<typename T, typename E>
00303 template<typename Graph, typename I>
00304 void ParallelIndicesCoarsener<T,E>::buildCoarseRemoteIndices(const RemoteIndices& fineRemote,
00305 const AggregatesMap<typename Graph::VertexDescriptor>& aggregates,
00306 ParallelIndexSet& coarseIndices,
00307 RemoteIndices& coarseRemote,
00308 ParallelAggregateRenumberer<Graph,I>& renumberer)
00309 {
00310 std::vector<char> attributes(static_cast<std::size_t>(renumberer));
00311
00312 GlobalLookupIndexSet<ParallelIndexSet> coarseLookup(coarseIndices, static_cast<std::size_t>(renumberer));
00313
00314 typedef typename RemoteIndices::const_iterator Iterator;
00315 Iterator end = fineRemote.end();
00316
00317 for(Iterator neighbour = fineRemote.begin();
00318 neighbour != end; ++neighbour){
00319 int process = neighbour->first;
00320
00321 assert(neighbour->second.first==neighbour->second.second);
00322
00323
00324 typedef typename std::vector<char>::iterator CIterator;
00325
00326 for(CIterator iter=attributes.begin(); iter!= attributes.end(); ++iter)
00327 *iter = std::numeric_limits<char>::max();
00328
00329 typedef typename RemoteIndices::RemoteIndexList::const_iterator Iterator;
00330 Iterator riEnd = neighbour->second.second->end();
00331
00332 for(Iterator index = neighbour->second.second->begin();
00333 index != riEnd; ++index){
00334 if(!E::contains(index->localIndexPair().local().attribute()) &&
00335 aggregates[index->localIndexPair().local()] !=
00336 AggregatesMap<typename Graph::VertexDescriptor>::ISOLATED)
00337 {
00338 assert(aggregates[index->localIndexPair().local()]<attributes.size());
00339 assert(attributes[aggregates[index->localIndexPair().local()]] == std::numeric_limits<char>::max()
00340 || attributes[aggregates[index->localIndexPair().local()]] == index->attribute());
00341 attributes[aggregates[index->localIndexPair().local()]] = index->attribute();
00342 }
00343 }
00344
00345
00346 typedef RemoteIndexListModifier<ParallelIndexSet,typename RemoteIndices::Allocator,false> Modifier;
00347 typedef typename RemoteIndices::RemoteIndex RemoteIndex;
00348 typedef typename ParallelIndexSet::const_iterator IndexIterator;
00349
00350 Modifier coarseList = coarseRemote.template getModifier<false,true>(process);
00351
00352 IndexIterator iend = coarseIndices.end();
00353 for(IndexIterator index = coarseIndices.begin(); index != iend; ++index)
00354 if(attributes[index->local()] != std::numeric_limits<char>::max()){
00355
00356 coarseList.insert(RemoteIndex(Attribute(attributes[index->local()]), &(*index)));
00357 }
00358
00359 }
00360
00361
00362 assert(coarseRemote.neighbours()==fineRemote.neighbours());
00363
00364
00365
00366 IndicesSyncer<ParallelIndexSet> syncer(coarseIndices, coarseRemote);
00367 syncer.sync(renumberer);
00368
00369 }
00370
00371 #endif
00372
00373 template<typename E>
00374 template<typename Graph, typename VM>
00375 typename Graph::VertexDescriptor
00376 IndicesCoarsener<SequentialInformation,E>::coarsen(const SequentialInformation& fineInfo,
00377 Graph& fineGraph,
00378 VM& visitedMap,
00379 AggregatesMap<typename Graph::VertexDescriptor>& aggregates,
00380 SequentialInformation& coarseInfo)
00381 {
00382 typedef typename Graph::VertexDescriptor Vertex;
00383 AggregateRenumberer<Graph> renumberer(aggregates);
00384 typedef typename Graph::VertexIterator Iterator;
00385
00386 for(Iterator vertex=fineGraph.begin(), endVertex=fineGraph.end();
00387 vertex != endVertex; ++vertex)
00388 if(aggregates[*vertex]!=AggregatesMap<Vertex>::ISOLATED &&
00389 !get(visitedMap, *vertex)){
00390
00391 aggregates.template breadthFirstSearch<false>(*vertex, aggregates[*vertex],
00392 fineGraph, renumberer, visitedMap);
00393 aggregates[*vertex] = renumberer;
00394 ++renumberer;
00395 }
00396
00397 for(Iterator vertex=fineGraph.begin(), endVertex=fineGraph.end();
00398 vertex != endVertex; ++vertex)
00399 put(visitedMap, *vertex, false);
00400
00401 return renumberer;
00402 }
00403
00404 }
00405 }
00406 #endif