00001
00002 #ifndef DUNE_GALERKIN_HH
00003 #define DUNE_GALERKIN_HH
00004
00005 #include"aggregates.hh"
00006 #include"pinfo.hh"
00007 #include<dune/common/poolallocator.hh>
00008 #include<dune/common/enumset.hh>
00009 #include<set>
00010 #include<limits>
00011 #include<algorithm>
00012
00013 namespace Dune
00014 {
00015 namespace Amg
00016 {
00028 template<class T>
00029 struct OverlapVertex
00030 {
00034 typedef T Aggregate;
00035
00039 typedef T Vertex;
00040
00044 Aggregate aggregate;
00045
00049 Vertex vertex;
00050 };
00051
00052
00053
00058 template<class M>
00059 class SparsityBuilder
00060 {
00061 public:
00067 SparsityBuilder(M& matrix);
00068
00069 void insert(const typename M::size_type& index);
00070
00071 void operator++();
00072
00073 std::size_t minRowSize();
00074
00075 std::size_t maxRowSize();
00076
00077 std::size_t sumRowSize();
00078 private:
00080 typename M::CreateIterator row_;
00082 std::size_t minRowSize_;
00084 std::size_t maxRowSize_;
00085 std::size_t sumRowSize_;
00086 #ifdef DUNE_ISTL_WITH_CHECKING
00087 bool diagonalInserted;
00088 #endif
00089 };
00090
00091 class BaseGalerkinProduct
00092 {
00093 public:
00102 template<class M, class V, class I, class O>
00103 void calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
00104 const I& pinfo, const O& copy);
00105
00106 };
00107
00108 template<class T>
00109 class GalerkinProduct
00110 : public BaseGalerkinProduct
00111 {
00112 public:
00113 typedef T ParallelInformation;
00114
00125 template<class M, class G, class V, class Set>
00126 M* build(const M& fine, G& fineGraph, V& visitedMap,
00127 const ParallelInformation& pinfo,
00128 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00129 const typename M::size_type& size,
00130 const Set& copy);
00131 private:
00132 std::size_t* overlapStart_;
00133
00140 template<class G, class I, class Set>
00141 const OverlapVertex<typename G::VertexDescriptor>*
00142 buildOverlapVertices(const G& graph, const I& pinfo,
00143 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00144 const Set& overlap,
00145 int& overlapCount);
00146
00147 template<class A>
00148 struct OVLess
00149 {
00150 bool operator()(const OverlapVertex<A>& o1, const OverlapVertex<A>& o2)
00151 {
00152 return o1.aggregate < o2.aggregate;
00153 }
00154 };
00155 };
00156
00157 template<>
00158 class GalerkinProduct<SequentialInformation>
00159 : public BaseGalerkinProduct
00160 {
00161 public:
00172 template<class M, class G, class V, class Set>
00173 M* build(const M& fine, G& fineGraph, V& visitedMap,
00174 const SequentialInformation& pinfo,
00175 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00176 const typename M::size_type& size,
00177 const Set& copy);
00178 };
00179
00180 struct BaseConnectivityConstructor
00181 {
00182 template<class R, class G, class V>
00183 static void constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
00184 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00185 const OverlapVertex<typename G::VertexDescriptor>*& seed,
00186 const OverlapVertex<typename G::VertexDescriptor>* overlapEnd);
00187
00191 template<class R, class G, class V>
00192 static void constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap,
00193 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00194 const typename G::VertexDescriptor& seed);
00195
00196
00200 template<class G, class S, class V>
00201 class ConnectedBuilder
00202 {
00203 public:
00207 typedef G Graph;
00211 typedef typename Graph::ConstEdgeIterator ConstEdgeIterator;
00212
00216 typedef S Set;
00217
00221 typedef V VisitedMap;
00222
00226 typedef typename Graph::VertexDescriptor Vertex;
00227
00235 ConnectedBuilder(const AggregatesMap<Vertex>& aggregates, Graph& graph,
00236 VisitedMap& visitedMap, Set& connected);
00237
00242 void operator()(const ConstEdgeIterator& edge);
00243
00244 private:
00248 const AggregatesMap<Vertex>& aggregates_;
00249
00250 Graph& graph_;
00251
00255 VisitedMap& visitedMap_;
00256
00260 Set& connected_;
00261 };
00262
00263 };
00264
00265 template<class G, class T>
00266 struct ConnectivityConstructor: public BaseConnectivityConstructor
00267 {
00268 typedef typename G::VertexDescriptor Vertex;
00269
00270 template<class V, class O, class R>
00271 static void examine(G& graph,
00272 V& visitedMap,
00273 const T& pinfo,
00274 const AggregatesMap<Vertex>& aggregates,
00275 const O& overlap,
00276 const std::size_t* overlapStart,
00277 const OverlapVertex<Vertex>* overlapVertices,
00278 const OverlapVertex<Vertex>* overlapEnd,
00279 R& row);
00280 };
00281
00282 template<class G>
00283 struct ConnectivityConstructor<G,SequentialInformation> : public BaseConnectivityConstructor
00284 {
00285 typedef typename G::VertexDescriptor Vertex;
00286
00287 template<class V, class R>
00288 static void examine(G& graph,
00289 V& visitedMap,
00290 const SequentialInformation& pinfo,
00291 const AggregatesMap<Vertex>& aggregates,
00292 R& row);
00293 };
00294
00295 template<class T>
00296 struct DirichletBoundarySetter
00297 {
00298 template<class M, class O>
00299 static void set(M& coarse, const T& pinfo, const O& copy);
00300 };
00301
00302 template<>
00303 struct DirichletBoundarySetter<SequentialInformation>
00304 {
00305 template<class M, class O>
00306 static void set(M& coarse, const SequentialInformation& pinfo, const O& copy);
00307 };
00308
00309 template<class R, class G, class V>
00310 void BaseConnectivityConstructor::constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap,
00311 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00312 const typename G::VertexDescriptor& seed)
00313 {
00314 row.insert(aggregates[seed]);
00315 ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
00316 typedef typename G::VertexDescriptor Vertex;
00317 typedef std::allocator<Vertex> Allocator;
00318 typedef SLList<Vertex,Allocator> VertexList;
00319 typedef typename AggregatesMap<Vertex>::DummyEdgeVisitor DummyVisitor;
00320 VertexList vlist;
00321 DummyVisitor dummy;
00322 aggregates.template breadthFirstSearch<true,false>(seed,aggregates[seed], graph, vlist, dummy,
00323 conBuilder, visitedMap);
00324 }
00325
00326 template<class R, class G, class V>
00327 void BaseConnectivityConstructor::constructOverlapConnectivity(R& row, G& graph, V& visitedMap,
00328 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00329 const OverlapVertex<typename G::VertexDescriptor>*& seed,
00330 const OverlapVertex<typename G::VertexDescriptor>* overlapEnd)
00331 {
00332 ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row);
00333 const typename G::VertexDescriptor aggregate=seed->aggregate;
00334
00335 while(seed != overlapEnd && aggregate == seed->aggregate){
00336 row.insert(seed->aggregate);
00337
00338 visitNeighbours(graph, seed->vertex, conBuilder);
00339
00340 put(visitedMap, seed->vertex, true);
00341 ++seed;
00342 }
00343 }
00344
00345 template<class G, class S, class V>
00346 BaseConnectivityConstructor::ConnectedBuilder<G,S,V>::ConnectedBuilder(const AggregatesMap<Vertex>& aggregates,
00347 Graph& graph, VisitedMap& visitedMap,
00348 Set& connected)
00349 : aggregates_(aggregates), graph_(graph), visitedMap_(visitedMap), connected_(connected)
00350 {}
00351
00352 template<class G, class S, class V>
00353 void BaseConnectivityConstructor::ConnectedBuilder<G,S,V>::operator()(const ConstEdgeIterator& edge)
00354 {
00355 typedef typename G::VertexDescriptor Vertex;
00356 const Vertex& vertex = aggregates_[edge.target()];
00357 assert(vertex!= AggregatesMap<Vertex>::UNAGGREGATED);
00358 if(vertex!= AggregatesMap<Vertex>::ISOLATED)
00359 connected_.insert(vertex);
00360 }
00361
00362 template<class T>
00363 template<class G, class I, class Set>
00364 const OverlapVertex<typename G::VertexDescriptor>*
00365 GalerkinProduct<T>::buildOverlapVertices(const G& graph, const I& pinfo,
00366 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00367 const Set& overlap,
00368 int& overlapCount)
00369 {
00370
00371 typedef typename G::ConstVertexIterator ConstIterator;
00372 typedef typename I::GlobalLookupIndexSet GlobalLookup;
00373 typedef typename GlobalLookup::IndexPair IndexPair;
00374
00375 const ConstIterator end = graph.end();
00376 overlapCount = 0;
00377
00378 const GlobalLookup& lookup=pinfo.globalLookup();
00379
00380 for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex){
00381 const IndexPair* pair = lookup.pair(*vertex);
00382
00383 if(pair!=0 && overlap.contains(pair->local().attribute()))
00384 ++overlapCount;
00385 }
00386
00387
00388 typedef typename G::VertexDescriptor Vertex;
00389
00390 OverlapVertex<Vertex>* overlapVertices = new OverlapVertex<Vertex>[overlapCount];
00391
00392
00393 overlapCount=0;
00394 for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex){
00395 const IndexPair* pair = lookup.pair(*vertex);
00396
00397 if(pair!=0 && overlap.contains(pair->local().attribute())){
00398 overlapVertices[overlapCount].aggregate = aggregates[pair->local()];
00399 overlapVertices[overlapCount].vertex = pair->local();
00400 ++overlapCount;
00401 }
00402 }
00403
00404 dverb << overlapCount<<" overlap vertices"<<std::endl;
00405
00406 std::sort(overlapVertices, overlapVertices+overlapCount, OVLess<Vertex>());
00407
00408 overlapStart_ = new std::size_t[graph.maxVertex()+1];
00409
00410 #ifndef NDEBUG
00411 for(typename G::VertexDescriptor i=typename G::VertexDescriptor(); i <= graph.maxVertex(); ++i)
00412 overlapStart_[i]=-1;
00413 #endif
00414
00415 std::size_t startIndex = 0;
00416
00417 Vertex aggregate = graph.maxVertex()+1;
00418 OverlapVertex<Vertex>* vend = overlapVertices+overlapCount;
00419
00420 for(OverlapVertex<Vertex>* vertex=overlapVertices; vertex != vend; ++vertex){
00421 if(aggregate != vertex->aggregate){
00422 aggregate = vertex->aggregate;
00423 startIndex=vertex-overlapVertices;
00424 }
00425 overlapStart_[vertex->vertex]=startIndex;
00426 }
00427 return overlapVertices;
00428 }
00429
00430 template<class G, class T>
00431 template<class V, class O, class R>
00432 void ConnectivityConstructor<G,T>::examine(G& graph,
00433 V& visitedMap,
00434 const T& pinfo,
00435 const AggregatesMap<Vertex>& aggregates,
00436 const O& overlap,
00437 const std::size_t* overlapStart,
00438 const OverlapVertex<Vertex>* overlapVertices,
00439 const OverlapVertex<Vertex>* overlapEnd,
00440 R& row)
00441 {
00442 typedef typename T::GlobalLookupIndexSet GlobalLookup;
00443 const GlobalLookup& lookup = pinfo.globalLookup();
00444
00445 typedef typename G::VertexIterator VertexIterator;
00446
00447 VertexIterator vend=graph.end();
00448
00449 #ifdef DUNE_ISTL_WITH_CHECKING
00450 std::set<Vertex> examined;
00451 #endif
00452
00453
00454
00455
00456 for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex)
00457 if(!get(visitedMap, *vertex)){
00458
00459 typedef typename GlobalLookup::IndexPair IndexPair;
00460 const IndexPair* pair = lookup.pair(*vertex);
00461 if(pair==0 || !overlap.contains(pair->local().attribute())){
00462 #ifdef DUNE_ISTL_WITH_CHECKING
00463 assert(examined.find(aggregates[*vertex])==examined.end());
00464 examined.insert(aggregates[*vertex]);
00465 #endif
00466 constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
00467 ++row;
00468 }
00469 }
00470
00471
00472
00473 while(overlapVertices != overlapEnd)
00474 if(overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED){
00475
00476 #ifdef DUNE_ISTL_WITH_CHECKING
00477 typedef typename GlobalLookup::IndexPair IndexPair;
00478 const IndexPair* pair = lookup.pair(overlapVertices->vertex);
00479 assert(pair!=0 && overlap.contains(pair->local().attribute()));
00480 assert(examined.find(aggregates[overlapVertices->vertex])==examined.end());
00481 examined.insert(aggregates[overlapVertices->vertex]);
00482 #endif
00483 constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd);
00484 ++row;
00485 }else{
00486 ++overlapVertices;
00487 }
00488 }
00489
00490 template<class G>
00491 template<class V, class R>
00492 void ConnectivityConstructor<G,SequentialInformation>::examine(G& graph,
00493 V& visitedMap,
00494 const SequentialInformation& pinfo,
00495 const AggregatesMap<Vertex>& aggregates,
00496 R& row)
00497 {
00498 typedef typename G::VertexIterator VertexIterator;
00499
00500 VertexIterator vend=graph.end();
00501 for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex){
00502 if(!get(visitedMap, *vertex)){
00503 constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex);
00504 ++row;
00505 }
00506 }
00507
00508 }
00509
00510 template<class M>
00511 SparsityBuilder<M>::SparsityBuilder(M& matrix)
00512 : row_(matrix.createbegin()),
00513 minRowSize_(std::numeric_limits<std::size_t>::max()),
00514 maxRowSize_(0), sumRowSize_(0)
00515 {
00516 #ifdef DUNE_ISTL_WITH_CHECKING
00517 diagonalInserted = false;
00518 #endif
00519 }
00520 template<class M>
00521 std::size_t SparsityBuilder<M>::maxRowSize()
00522 {
00523 return maxRowSize_;
00524 }
00525 template<class M>
00526 std::size_t SparsityBuilder<M>::minRowSize()
00527 {
00528 return minRowSize_;
00529 }
00530
00531 template<class M>
00532 std::size_t SparsityBuilder<M>::sumRowSize()
00533 {
00534 return sumRowSize_;
00535 }
00536 template<class M>
00537 void SparsityBuilder<M>::operator++()
00538 {
00539 sumRowSize_ += row_.size();
00540 minRowSize_=std::min(minRowSize_, row_.size());
00541 maxRowSize_=std::max(maxRowSize_, row_.size());
00542 ++row_;
00543 #ifdef DUNE_ISTL_WITH_CHECKING
00544 assert(diagonalInserted);
00545 diagonalInserted = false;
00546 #endif
00547 }
00548
00549 template<class M>
00550 void SparsityBuilder<M>::insert(const typename M::size_type& index)
00551 {
00552 row_.insert(index);
00553 #ifdef DUNE_ISTL_WITH_CHECKING
00554 diagonalInserted = diagonalInserted || row_.index()==index;
00555 #endif
00556 }
00557
00558 template<class T>
00559 template<class M, class G, class V, class Set>
00560 M* GalerkinProduct<T>::build(const M& fine, G& fineGraph, V& visitedMap,
00561 const ParallelInformation& pinfo,
00562 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00563 const typename M::size_type& size,
00564 const Set& overlap)
00565 {
00566
00567 typedef OverlapVertex<typename G::VertexDescriptor> OverlapVertex;
00568
00569 int count;
00570
00571 const OverlapVertex* overlapVertices = buildOverlapVertices(fineGraph,
00572 pinfo,
00573 aggregates,
00574 overlap,
00575 count);
00576 M* coarseMatrix = new M(size, size, M::row_wise);
00577
00578
00579
00580
00581 typedef typename G::VertexIterator Vertex;
00582 Vertex vend = fineGraph.end();
00583 for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex){
00584 assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED);
00585 put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED);
00586 }
00587
00588 SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
00589
00590 ConnectivityConstructor<G,T>::examine(fineGraph, visitedMap, pinfo,
00591 aggregates, overlap, overlapStart_,
00592 overlapVertices,
00593 overlapVertices+count,
00594 sparsityBuilder);
00595
00596 dinfo<<pinfo.communicator().rank()<<": Matrix ("<<coarseMatrix->N()<<"x"<<coarseMatrix->M()<<" row: min="<<sparsityBuilder.minRowSize()<<" max="
00597 <<sparsityBuilder.maxRowSize()<<" avg="
00598 <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()
00599 <<std::endl;
00600
00601 delete[] overlapVertices;
00602 delete[] overlapStart_;
00603
00604
00605
00606 return coarseMatrix;
00607 }
00608
00609 template<class M, class G, class V, class Set>
00610 M* GalerkinProduct<SequentialInformation>::build(const M& fine, G& fineGraph, V& visitedMap,
00611 const SequentialInformation& pinfo,
00612 const AggregatesMap<typename G::VertexDescriptor>& aggregates,
00613 const typename M::size_type& size,
00614 const Set& overlap)
00615 {
00616 M* coarseMatrix = new M(size, size, M::row_wise);
00617
00618
00619
00620
00621 typedef typename G::VertexIterator Vertex;
00622 Vertex vend = fineGraph.end();
00623 for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex){
00624 assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED);
00625 put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED);
00626 }
00627
00628 SparsityBuilder<M> sparsityBuilder(*coarseMatrix);
00629
00630 ConnectivityConstructor<G,SequentialInformation>::examine(fineGraph, visitedMap, pinfo,
00631 aggregates, sparsityBuilder);
00632 dinfo<<"Matrix row: min="<<sparsityBuilder.minRowSize()<<" max="
00633 <<sparsityBuilder.maxRowSize()<<" average="
00634 <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()<<std::endl;
00635 return coarseMatrix;
00636 }
00637
00638 template<class M, class V, class P, class O>
00639 void BaseGalerkinProduct::calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse,
00640 const P& pinfo, const O& copy)
00641 {
00642 coarse = static_cast<typename M::field_type>(0);
00643
00644 typedef typename M::ConstIterator RowIterator;
00645 RowIterator endRow = fine.end();
00646
00647 for(RowIterator row = fine.begin(); row != endRow; ++row)
00648 if(aggregates[row.index()] != AggregatesMap<V>::ISOLATED){
00649 assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
00650
00651 typedef typename M::ConstColIterator ColIterator;
00652 ColIterator endCol = row->end();
00653
00654 for(ColIterator col = row->begin(); col != endCol; ++col)
00655 if(aggregates[col.index()] != AggregatesMap<V>::ISOLATED){
00656 assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED);
00657 coarse[aggregates[row.index()]][aggregates[col.index()]]+=*col;
00658 }
00659 }
00660
00661
00662 DirichletBoundarySetter<P>::template set<M>(coarse, pinfo, copy);
00663
00664 }
00665
00666 template<class T>
00667 template<class M, class O>
00668 void DirichletBoundarySetter<T>::set(M& coarse, const T& pinfo, const O& copy)
00669 {
00670 typedef typename T::ParallelIndexSet::const_iterator ConstIterator;
00671 ConstIterator end = pinfo.indexSet().end();
00672 typedef typename M::block_type Block;
00673 Block identity=Block(0.0);
00674 for(typename Block::RowIterator b=identity.begin(); b != identity.end(); ++b)
00675 b->operator[](b.index())=1.0;
00676
00677 for(ConstIterator index = pinfo.indexSet().begin();
00678 index != end; ++index){
00679 if(copy.contains(index->local().attribute())){
00680 typedef typename M::ColIterator ColIterator;
00681 typedef typename M::row_type Row;
00682 Row row = coarse[index->local()];
00683 ColIterator cend = row.find(index->local());
00684 ColIterator col = row.begin();
00685 for(; col != cend; ++col)
00686 *col = 0;
00687
00688 cend = row.end();
00689
00690 assert(col != cend);
00691 *col = identity;
00692
00693 for(++col; col != cend; ++col)
00694 *col = 0;
00695 }
00696 }
00697 }
00698
00699 template<class M, class O>
00700 void DirichletBoundarySetter<SequentialInformation>::set(M& coarse,
00701 const SequentialInformation& pinfo,
00702 const O& overlap)
00703 {
00704 }
00705
00706 }
00707 }
00708 #endif