dune-istl
2.1.1
|
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 00002 // vi: set ts=8 sw=2 et sts=2: 00003 // $Id: galerkin.hh 1444 2011-01-23 17:24:33Z rebecca $ 00004 #ifndef DUNE_GALERKIN_HH 00005 #define DUNE_GALERKIN_HH 00006 00007 #include"aggregates.hh" 00008 #include"pinfo.hh" 00009 #include<dune/common/poolallocator.hh> 00010 #include<dune/common/enumset.hh> 00011 #include<set> 00012 #include<limits> 00013 #include<algorithm> 00014 00015 namespace Dune 00016 { 00017 namespace Amg 00018 { 00030 template<class T> 00031 struct OverlapVertex 00032 { 00036 typedef T Aggregate; 00037 00041 typedef T Vertex; 00042 00046 Aggregate* aggregate; 00047 00051 Vertex vertex; 00052 }; 00053 00054 00055 00060 template<class M> 00061 class SparsityBuilder 00062 { 00063 public: 00069 SparsityBuilder(M& matrix); 00070 00071 void insert(const typename M::size_type& index); 00072 00073 void operator++(); 00074 00075 std::size_t minRowSize(); 00076 00077 std::size_t maxRowSize(); 00078 00079 std::size_t sumRowSize(); 00080 std::size_t index() 00081 { 00082 return row_.index(); 00083 } 00084 private: 00086 typename M::CreateIterator row_; 00088 std::size_t minRowSize_; 00090 std::size_t maxRowSize_; 00091 std::size_t sumRowSize_; 00092 #ifdef DUNE_ISTL_WITH_CHECKING 00093 bool diagonalInserted; 00094 #endif 00095 }; 00096 00097 class BaseGalerkinProduct 00098 { 00099 public: 00108 template<class M, class V, class I, class O> 00109 void calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse, 00110 const I& pinfo, const O& copy); 00111 00112 }; 00113 00114 template<class T> 00115 class GalerkinProduct 00116 : public BaseGalerkinProduct 00117 { 00118 public: 00119 typedef T ParallelInformation; 00120 00131 template<class M, class G, class V, class Set> 00132 M* build(const M& fine, G& fineGraph, V& visitedMap, 00133 const ParallelInformation& pinfo, 00134 AggregatesMap<typename G::VertexDescriptor>& aggregates, 00135 const typename M::size_type& size, 00136 const Set& copy); 00137 private: 00138 00145 template<class G, class I, class Set> 00146 const OverlapVertex<typename G::VertexDescriptor>* 00147 buildOverlapVertices(const G& graph, const I& pinfo, 00148 AggregatesMap<typename G::VertexDescriptor>& aggregates, 00149 const Set& overlap, 00150 std::size_t& overlapCount); 00151 00152 template<class A> 00153 struct OVLess 00154 { 00155 bool operator()(const OverlapVertex<A>& o1, const OverlapVertex<A>& o2) 00156 { 00157 return *o1.aggregate < *o2.aggregate; 00158 } 00159 }; 00160 }; 00161 00162 template<> 00163 class GalerkinProduct<SequentialInformation> 00164 : public BaseGalerkinProduct 00165 { 00166 public: 00177 template<class M, class G, class V, class Set> 00178 M* build(const M& fine, G& fineGraph, V& visitedMap, 00179 const SequentialInformation& pinfo, 00180 const AggregatesMap<typename G::VertexDescriptor>& aggregates, 00181 const typename M::size_type& size, 00182 const Set& copy); 00183 }; 00184 00185 struct BaseConnectivityConstructor 00186 { 00187 template<class R, class G, class V> 00188 static void constructOverlapConnectivity(R& row, G& graph, V& visitedMap, 00189 const AggregatesMap<typename G::VertexDescriptor>& aggregates, 00190 const OverlapVertex<typename G::VertexDescriptor>*& seed, 00191 const OverlapVertex<typename G::VertexDescriptor>* overlapEnd); 00192 00196 template<class R, class G, class V> 00197 static void constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap, 00198 const AggregatesMap<typename G::VertexDescriptor>& aggregates, 00199 const typename G::VertexDescriptor& seed); 00200 00201 00205 template<class G, class S, class V> 00206 class ConnectedBuilder 00207 { 00208 public: 00212 typedef G Graph; 00216 typedef typename Graph::ConstEdgeIterator ConstEdgeIterator; 00217 00221 typedef S Set; 00222 00226 typedef V VisitedMap; 00227 00231 typedef typename Graph::VertexDescriptor Vertex; 00232 00240 ConnectedBuilder(const AggregatesMap<Vertex>& aggregates, Graph& graph, 00241 VisitedMap& visitedMap, Set& connected); 00242 00247 void operator()(const ConstEdgeIterator& edge); 00248 00249 private: 00253 const AggregatesMap<Vertex>& aggregates_; 00254 00255 Graph& graph_; 00256 00260 VisitedMap& visitedMap_; 00261 00265 Set& connected_; 00266 }; 00267 00268 }; 00269 00270 template<class G, class T> 00271 struct ConnectivityConstructor: public BaseConnectivityConstructor 00272 { 00273 typedef typename G::VertexDescriptor Vertex; 00274 00275 template<class V, class O, class R> 00276 static void examine(G& graph, 00277 V& visitedMap, 00278 const T& pinfo, 00279 const AggregatesMap<Vertex>& aggregates, 00280 const O& overlap, 00281 const OverlapVertex<Vertex>* overlapVertices, 00282 const OverlapVertex<Vertex>* overlapEnd, 00283 R& row); 00284 }; 00285 00286 template<class G> 00287 struct ConnectivityConstructor<G,SequentialInformation> : public BaseConnectivityConstructor 00288 { 00289 typedef typename G::VertexDescriptor Vertex; 00290 00291 template<class V, class R> 00292 static void examine(G& graph, 00293 V& visitedMap, 00294 const SequentialInformation& pinfo, 00295 const AggregatesMap<Vertex>& aggregates, 00296 R& row); 00297 }; 00298 00299 template<class T> 00300 struct DirichletBoundarySetter 00301 { 00302 template<class M, class O> 00303 static void set(M& coarse, const T& pinfo, const O& copy); 00304 }; 00305 00306 template<> 00307 struct DirichletBoundarySetter<SequentialInformation> 00308 { 00309 template<class M, class O> 00310 static void set(M& coarse, const SequentialInformation& pinfo, const O& copy); 00311 }; 00312 00313 template<class R, class G, class V> 00314 void BaseConnectivityConstructor::constructNonOverlapConnectivity(R& row, G& graph, V& visitedMap, 00315 const AggregatesMap<typename G::VertexDescriptor>& aggregates, 00316 const typename G::VertexDescriptor& seed) 00317 { 00318 assert(row.index()==aggregates[seed]); 00319 row.insert(aggregates[seed]); 00320 ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row); 00321 typedef typename G::VertexDescriptor Vertex; 00322 typedef std::allocator<Vertex> Allocator; 00323 typedef SLList<Vertex,Allocator> VertexList; 00324 typedef typename AggregatesMap<Vertex>::DummyEdgeVisitor DummyVisitor; 00325 VertexList vlist; 00326 DummyVisitor dummy; 00327 aggregates.template breadthFirstSearch<true,false>(seed,aggregates[seed], graph, vlist, dummy, 00328 conBuilder, visitedMap); 00329 } 00330 00331 template<class R, class G, class V> 00332 void BaseConnectivityConstructor::constructOverlapConnectivity(R& row, G& graph, V& visitedMap, 00333 const AggregatesMap<typename G::VertexDescriptor>& aggregates, 00334 const OverlapVertex<typename G::VertexDescriptor>*& seed, 00335 const OverlapVertex<typename G::VertexDescriptor>* overlapEnd) 00336 { 00337 ConnectedBuilder<G,R,V> conBuilder(aggregates, graph, visitedMap, row); 00338 const typename G::VertexDescriptor aggregate=*seed->aggregate; 00339 assert(row.index()==*seed->aggregate); 00340 00341 while(seed != overlapEnd && aggregate == *seed->aggregate){ 00342 row.insert(*seed->aggregate); 00343 // Walk over all neighbours and add them to the connected array. 00344 visitNeighbours(graph, seed->vertex, conBuilder); 00345 // Mark vertex as visited 00346 put(visitedMap, seed->vertex, true); 00347 ++seed; 00348 } 00349 } 00350 00351 template<class G, class S, class V> 00352 BaseConnectivityConstructor::ConnectedBuilder<G,S,V>::ConnectedBuilder(const AggregatesMap<Vertex>& aggregates, 00353 Graph& graph, VisitedMap& visitedMap, 00354 Set& connected) 00355 : aggregates_(aggregates), graph_(graph), visitedMap_(visitedMap), connected_(connected) 00356 {} 00357 00358 template<class G, class S, class V> 00359 void BaseConnectivityConstructor::ConnectedBuilder<G,S,V>::operator()(const ConstEdgeIterator& edge) 00360 { 00361 typedef typename G::VertexDescriptor Vertex; 00362 const Vertex& vertex = aggregates_[edge.target()]; 00363 assert(vertex!= AggregatesMap<Vertex>::UNAGGREGATED); 00364 if(vertex!= AggregatesMap<Vertex>::ISOLATED) 00365 connected_.insert(vertex); 00366 } 00367 00368 template<class T> 00369 template<class G, class I, class Set> 00370 const OverlapVertex<typename G::VertexDescriptor>* 00371 GalerkinProduct<T>::buildOverlapVertices(const G& graph, const I& pinfo, 00372 AggregatesMap<typename G::VertexDescriptor>& aggregates, 00373 const Set& overlap, 00374 std::size_t& overlapCount) 00375 { 00376 // count the overlap vertices. 00377 typedef typename G::ConstVertexIterator ConstIterator; 00378 typedef typename I::GlobalLookupIndexSet GlobalLookup; 00379 typedef typename GlobalLookup::IndexPair IndexPair; 00380 00381 const ConstIterator end = graph.end(); 00382 overlapCount = 0; 00383 00384 const GlobalLookup& lookup=pinfo.globalLookup(); 00385 00386 for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex){ 00387 const IndexPair* pair = lookup.pair(*vertex); 00388 00389 if(pair!=0 && overlap.contains(pair->local().attribute())) 00390 ++overlapCount; 00391 } 00392 // Allocate space 00393 typedef typename G::VertexDescriptor Vertex; 00394 00395 OverlapVertex<Vertex>* overlapVertices = new OverlapVertex<Vertex>[overlapCount=0?1:overlapCount]; 00396 if(overlapCount==0) 00397 return overlapVertices; 00398 00399 // Initialize them 00400 overlapCount=0; 00401 for(ConstIterator vertex=graph.begin(); vertex != end; ++vertex){ 00402 const IndexPair* pair = lookup.pair(*vertex); 00403 00404 if(pair!=0 && overlap.contains(pair->local().attribute())){ 00405 overlapVertices[overlapCount].aggregate = &aggregates[pair->local()]; 00406 overlapVertices[overlapCount].vertex = pair->local(); 00407 ++overlapCount; 00408 } 00409 } 00410 00411 dverb << overlapCount<<" overlap vertices"<<std::endl; 00412 00413 std::sort(overlapVertices, overlapVertices+overlapCount, OVLess<Vertex>()); 00414 // due to the sorting the isolated aggregates (to be skipped) are at the end. 00415 00416 return overlapVertices; 00417 } 00418 00419 template<class G, class T> 00420 template<class V, class O, class R> 00421 void ConnectivityConstructor<G,T>::examine(G& graph, 00422 V& visitedMap, 00423 const T& pinfo, 00424 const AggregatesMap<Vertex>& aggregates, 00425 const O& overlap, 00426 const OverlapVertex<Vertex>* overlapVertices, 00427 const OverlapVertex<Vertex>* overlapEnd, 00428 R& row) 00429 { 00430 typedef typename T::GlobalLookupIndexSet GlobalLookup; 00431 const GlobalLookup& lookup = pinfo.globalLookup(); 00432 00433 typedef typename G::VertexIterator VertexIterator; 00434 00435 VertexIterator vend=graph.end(); 00436 00437 #ifdef DUNE_ISTL_WITH_CHECKING 00438 std::set<Vertex> examined; 00439 #endif 00440 00441 // The aggregates owned by the process have lower local indices 00442 // then those not owned. We process them in the first pass. 00443 // They represent the rows 0, 1, ..., n of the coarse matrix 00444 for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex) 00445 if(!get(visitedMap, *vertex)){ 00446 // In the first pass we only process owner nodes 00447 typedef typename GlobalLookup::IndexPair IndexPair; 00448 const IndexPair* pair = lookup.pair(*vertex); 00449 if(pair==0 || !overlap.contains(pair->local().attribute())){ 00450 #ifdef DUNE_ISTL_WITH_CHECKING 00451 assert(examined.find(aggregates[*vertex])==examined.end()); 00452 examined.insert(aggregates[*vertex]); 00453 #endif 00454 constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex); 00455 ++row; 00456 } 00457 } 00458 00459 #ifdef DUNE_ISTL_WITH_CHECKING 00460 std::cout<<"constructed "<<row.index()<<" non-overlapping rows"<<std::endl; 00461 #endif 00462 00463 // Now come the aggregates not owned by use. 00464 // They represent the rows n+1, ..., N 00465 while(overlapVertices != overlapEnd) 00466 if(*overlapVertices->aggregate!=AggregatesMap<Vertex>::ISOLATED){ 00467 00468 #ifdef DUNE_ISTL_WITH_CHECKING 00469 typedef typename GlobalLookup::IndexPair IndexPair; 00470 const IndexPair* pair = lookup.pair(overlapVertices->vertex); 00471 assert(pair!=0 && overlap.contains(pair->local().attribute())); 00472 assert(examined.find(aggregates[overlapVertices->vertex])==examined.end()); 00473 examined.insert(aggregates[overlapVertices->vertex]); 00474 #endif 00475 constructOverlapConnectivity(row, graph, visitedMap, aggregates, overlapVertices, overlapEnd); 00476 ++row; 00477 }else{ 00478 ++overlapVertices; 00479 } 00480 } 00481 00482 template<class G> 00483 template<class V, class R> 00484 void ConnectivityConstructor<G,SequentialInformation>::examine(G& graph, 00485 V& visitedMap, 00486 const SequentialInformation& pinfo, 00487 const AggregatesMap<Vertex>& aggregates, 00488 R& row) 00489 { 00490 typedef typename G::VertexIterator VertexIterator; 00491 00492 VertexIterator vend=graph.end(); 00493 for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex){ 00494 if(!get(visitedMap, *vertex)){ 00495 constructNonOverlapConnectivity(row, graph, visitedMap, aggregates, *vertex); 00496 ++row; 00497 } 00498 } 00499 00500 } 00501 00502 template<class M> 00503 SparsityBuilder<M>::SparsityBuilder(M& matrix) 00504 : row_(matrix.createbegin()), 00505 minRowSize_(std::numeric_limits<std::size_t>::max()), 00506 maxRowSize_(0), sumRowSize_(0) 00507 { 00508 #ifdef DUNE_ISTL_WITH_CHECKING 00509 diagonalInserted = false; 00510 #endif 00511 } 00512 template<class M> 00513 std::size_t SparsityBuilder<M>::maxRowSize() 00514 { 00515 return maxRowSize_; 00516 } 00517 template<class M> 00518 std::size_t SparsityBuilder<M>::minRowSize() 00519 { 00520 return minRowSize_; 00521 } 00522 00523 template<class M> 00524 std::size_t SparsityBuilder<M>::sumRowSize() 00525 { 00526 return sumRowSize_; 00527 } 00528 template<class M> 00529 void SparsityBuilder<M>::operator++() 00530 { 00531 sumRowSize_ += row_.size(); 00532 minRowSize_=std::min(minRowSize_, row_.size()); 00533 maxRowSize_=std::max(maxRowSize_, row_.size()); 00534 ++row_; 00535 #ifdef DUNE_ISTL_WITH_CHECKING 00536 assert(diagonalInserted); 00537 diagonalInserted = false; 00538 #endif 00539 } 00540 00541 template<class M> 00542 void SparsityBuilder<M>::insert(const typename M::size_type& index) 00543 { 00544 row_.insert(index); 00545 #ifdef DUNE_ISTL_WITH_CHECKING 00546 diagonalInserted = diagonalInserted || row_.index()==index; 00547 #endif 00548 } 00549 00550 template<class T> 00551 template<class M, class G, class V, class Set> 00552 M* GalerkinProduct<T>::build(const M& fine, G& fineGraph, V& visitedMap, 00553 const ParallelInformation& pinfo, 00554 AggregatesMap<typename G::VertexDescriptor>& aggregates, 00555 const typename M::size_type& size, 00556 const Set& overlap) 00557 { 00558 00559 typedef OverlapVertex<typename G::VertexDescriptor> OverlapVertex; 00560 00561 std::size_t count; 00562 00563 const OverlapVertex* overlapVertices = buildOverlapVertices(fineGraph, 00564 pinfo, 00565 aggregates, 00566 overlap, 00567 count); 00568 M* coarseMatrix = new M(size, size, M::row_wise); 00569 00570 // Reset the visited flags of all vertices. 00571 // As the isolated nodes will be skipped we simply mark them as visited 00572 00573 typedef typename G::VertexIterator Vertex; 00574 Vertex vend = fineGraph.end(); 00575 for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex){ 00576 assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED); 00577 put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED); 00578 } 00579 00580 SparsityBuilder<M> sparsityBuilder(*coarseMatrix); 00581 00582 ConnectivityConstructor<G,T>::examine(fineGraph, visitedMap, pinfo, 00583 aggregates, overlap, 00584 overlapVertices, 00585 overlapVertices+count, 00586 sparsityBuilder); 00587 00588 dinfo<<pinfo.communicator().rank()<<": Matrix ("<<coarseMatrix->N()<<"x"<<coarseMatrix->M()<<" row: min="<<sparsityBuilder.minRowSize()<<" max=" 00589 <<sparsityBuilder.maxRowSize()<<" avg=" 00590 <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N() 00591 <<std::endl; 00592 00593 delete[] overlapVertices; 00594 00595 //calculate(fine, aggregates, *coarse, overlap); 00596 00597 return coarseMatrix; 00598 } 00599 00600 template<class M, class G, class V, class Set> 00601 M* GalerkinProduct<SequentialInformation>::build(const M& fine, G& fineGraph, V& visitedMap, 00602 const SequentialInformation& pinfo, 00603 const AggregatesMap<typename G::VertexDescriptor>& aggregates, 00604 const typename M::size_type& size, 00605 const Set& overlap) 00606 { 00607 M* coarseMatrix = new M(size, size, M::row_wise); 00608 00609 // Reset the visited flags of all vertices. 00610 // As the isolated nodes will be skipped we simply mark them as visited 00611 00612 typedef typename G::VertexIterator Vertex; 00613 Vertex vend = fineGraph.end(); 00614 for(Vertex vertex = fineGraph.begin(); vertex != vend; ++vertex){ 00615 assert(aggregates[*vertex] != AggregatesMap<typename G::VertexDescriptor>::UNAGGREGATED); 00616 put(visitedMap, *vertex, aggregates[*vertex]==AggregatesMap<typename G::VertexDescriptor>::ISOLATED); 00617 } 00618 00619 SparsityBuilder<M> sparsityBuilder(*coarseMatrix); 00620 00621 ConnectivityConstructor<G,SequentialInformation>::examine(fineGraph, visitedMap, pinfo, 00622 aggregates, sparsityBuilder); 00623 dinfo<<"Matrix row: min="<<sparsityBuilder.minRowSize()<<" max=" 00624 <<sparsityBuilder.maxRowSize()<<" average=" 00625 <<static_cast<double>(sparsityBuilder.sumRowSize())/coarseMatrix->N()<<std::endl; 00626 return coarseMatrix; 00627 } 00628 00629 template<class M, class V, class P, class O> 00630 void BaseGalerkinProduct::calculate(const M& fine, const AggregatesMap<V>& aggregates, M& coarse, 00631 const P& pinfo, const O& copy) 00632 { 00633 coarse = static_cast<typename M::field_type>(0); 00634 00635 typedef typename M::ConstIterator RowIterator; 00636 RowIterator endRow = fine.end(); 00637 00638 for(RowIterator row = fine.begin(); row != endRow; ++row) 00639 if(aggregates[row.index()] != AggregatesMap<V>::ISOLATED){ 00640 assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED); 00641 typedef typename M::ConstColIterator ColIterator; 00642 ColIterator endCol = row->end(); 00643 00644 for(ColIterator col = row->begin(); col != endCol; ++col) 00645 if(aggregates[col.index()] != AggregatesMap<V>::ISOLATED){ 00646 assert(aggregates[row.index()]!=AggregatesMap<V>::UNAGGREGATED); 00647 coarse[aggregates[row.index()]][aggregates[col.index()]]+=*col; 00648 } 00649 } 00650 00651 // get the right diagonal matrix values on copy lines from owner processes 00652 typedef typename M::block_type BlockType; 00653 std::vector<BlockType> rowsize(coarse.N(),BlockType(0)); 00654 for (RowIterator row = coarse.begin(); row != coarse.end(); ++row) 00655 rowsize[row.index()]=coarse[row.index()][row.index()]; 00656 pinfo.copyOwnerToAll(rowsize,rowsize); 00657 for (RowIterator row = coarse.begin(); row != coarse.end(); ++row) 00658 coarse[row.index()][row.index()] = rowsize[row.index()]; 00659 00660 // don't set dirichlet boundaries for copy lines to make novlp case work, 00661 // the preconditioner yields slightly different results now. 00662 00663 // Set the dirichlet border 00664 //DirichletBoundarySetter<P>::template set<M>(coarse, pinfo, copy); 00665 00666 } 00667 00668 template<class T> 00669 template<class M, class O> 00670 void DirichletBoundarySetter<T>::set(M& coarse, const T& pinfo, const O& copy) 00671 { 00672 typedef typename T::ParallelIndexSet::const_iterator ConstIterator; 00673 ConstIterator end = pinfo.indexSet().end(); 00674 typedef typename M::block_type Block; 00675 Block identity=Block(0.0); 00676 for(typename Block::RowIterator b=identity.begin(); b != identity.end(); ++b) 00677 b->operator[](b.index())=1.0; 00678 00679 for(ConstIterator index = pinfo.indexSet().begin(); 00680 index != end; ++index){ 00681 if(copy.contains(index->local().attribute())){ 00682 typedef typename M::ColIterator ColIterator; 00683 typedef typename M::row_type Row; 00684 Row row = coarse[index->local()]; 00685 ColIterator cend = row.find(index->local()); 00686 ColIterator col = row.begin(); 00687 for(; col != cend; ++col) 00688 *col = 0; 00689 00690 cend = row.end(); 00691 00692 assert(col != cend); // There should be a diagonal entry 00693 *col = identity; 00694 00695 for(++col; col != cend; ++col) 00696 *col = 0; 00697 } 00698 } 00699 } 00700 00701 template<class M, class O> 00702 void DirichletBoundarySetter<SequentialInformation>::set(M& coarse, 00703 const SequentialInformation& pinfo, 00704 const O& overlap) 00705 { 00706 } 00707 00708 }// namespace Amg 00709 }// namespace Dune 00710 #endif