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