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