00001 #ifndef DUNE_AMGSMOOTHER_HH
00002 #define DUNE_AMGSMOOTHER_HH
00003
00004 #include<dune/istl/paamg/construction.hh>
00005 #include<dune/istl/paamg/aggregates.hh>
00006 #include<dune/istl/preconditioners.hh>
00007 #include<dune/istl/schwarz.hh>
00008 #include<dune/common/propertymap.hh>
00009
00010 namespace Dune
00011 {
00012 namespace Amg
00013 {
00014
00030 template<class T>
00031 struct DefaultSmootherArgs
00032 {
00036 typedef T RelaxationFactor;
00037
00041 int iterations;
00045 RelaxationFactor relaxationFactor;
00046
00050 DefaultSmootherArgs()
00051 : iterations(1), relaxationFactor(1.0)
00052 {}
00053 };
00054
00058 template<class T>
00059 struct SmootherTraits
00060 {
00061 typedef DefaultSmootherArgs<typename T::matrix_type::field_type> Arguments;
00062
00063 };
00064
00065 template<class X, class Y, class C, class T>
00066 struct SmootherTraits<BlockPreconditioner<X,Y,C,T> >
00067 {
00068 typedef DefaultSmootherArgs<typename T::matrix_type::field_type> Arguments;
00069
00070 };
00071
00072
00076 template<class T>
00077 class DefaultConstructionArgs
00078 {
00079 typedef typename T::matrix_type Matrix;
00080
00081 typedef typename SmootherTraits<T>::Arguments SmootherArgs;
00082
00083 typedef Dune::Amg::AggregatesMap<typename MatrixGraph<Matrix>::VertexDescriptor> AggregatesMap;
00084
00085 public:
00086 virtual ~DefaultConstructionArgs()
00087 {}
00088
00089 void setMatrix(const Matrix& matrix)
00090 {
00091 matrix_=&matrix;
00092 }
00093 virtual void setMatrix(const Matrix& matrix, const AggregatesMap& amap)
00094 {
00095 setMatrix(matrix);
00096 }
00097
00098
00099 const Matrix& getMatrix() const
00100 {
00101 return *matrix_;
00102 }
00103
00104 void setArgs(const SmootherArgs& args)
00105 {
00106 args_=&args;
00107 }
00108
00109 template<class T1>
00110 void setComm(T1& comm)
00111 {}
00112
00113 const SmootherArgs getArgs() const
00114 {
00115 return *args_;
00116 }
00117
00118 protected:
00119 const Matrix* matrix_;
00120 private:
00121 const SmootherArgs* args_;
00122 };
00123
00124 template<class T>
00125 struct ConstructionArgs
00126 : public DefaultConstructionArgs<T>
00127 {};
00128
00129 template<class T, class C=SequentialInformation>
00130 class DefaultParallelConstructionArgs
00131 : public ConstructionArgs<T>
00132 {
00133 public:
00134 virtual ~DefaultParallelConstructionArgs()
00135 {}
00136
00137 void setComm(const C& comm)
00138 {
00139 comm_ = &comm;
00140 }
00141
00142 const C& getComm() const
00143 {
00144 return *comm_;
00145 }
00146 private:
00147 const C* comm_;
00148 };
00149
00150
00151 template<class T>
00152 class ConstructionTraits;
00153
00157 template<class M, class X, class Y, int l>
00158 struct ConstructionTraits<SeqSSOR<M,X,Y,l> >
00159 {
00160 typedef DefaultConstructionArgs<SeqSSOR<M,X,Y,l> > Arguments;
00161
00162 static inline SeqSSOR<M,X,Y,l>* construct(Arguments& args)
00163 {
00164 return new SeqSSOR<M,X,Y,l>(args.getMatrix(), args.getArgs().iterations,
00165 args.getArgs().relaxationFactor);
00166 }
00167
00168 static inline void deconstruct(SeqSSOR<M,X,Y,l>* ssor)
00169 {
00170 delete ssor;
00171 }
00172
00173 };
00174
00175
00179 template<class M, class X, class Y, int l>
00180 struct ConstructionTraits<SeqSOR<M,X,Y,l> >
00181 {
00182 typedef DefaultConstructionArgs<SeqSOR<M,X,Y,l> > Arguments;
00183
00184 static inline SeqSOR<M,X,Y,l>* construct(Arguments& args)
00185 {
00186 return new SeqSOR<M,X,Y,l>(args.getMatrix(), args.getArgs().iterations,
00187 args.getArgs().relaxationFactor);
00188 }
00189
00190 static inline void deconstruct(SeqSOR<M,X,Y,l>* sor)
00191 {
00192 delete sor;
00193 }
00194
00195 };
00199 template<class M, class X, class Y, int l>
00200 struct ConstructionTraits<SeqJac<M,X,Y,l> >
00201 {
00202 typedef DefaultConstructionArgs<SeqJac<M,X,Y,l> > Arguments;
00203
00204 static inline SeqJac<M,X,Y,l>* construct(Arguments& args)
00205 {
00206 return new SeqJac<M,X,Y,l>(args.getMatrix(), args.getArgs().iterations,
00207 args.getArgs().relaxationFactor);
00208 }
00209
00210 static void deconstruct(SeqJac<M,X,Y,l>* jac)
00211 {
00212 delete jac;
00213 }
00214
00215 };
00216
00217
00221 template<class M, class X, class Y>
00222 struct ConstructionTraits<SeqILU0<M,X,Y> >
00223 {
00224 typedef DefaultConstructionArgs<SeqILU0<M,X,Y> > Arguments;
00225
00226 static inline SeqILU0<M,X,Y>* construct(Arguments& args)
00227 {
00228 return new SeqILU0<M,X,Y>(args.getMatrix(),
00229 args.getArgs().relaxationFactor);
00230 }
00231
00232 static void deconstruct(SeqILU0<M,X,Y>* ilu)
00233 {
00234 delete ilu;
00235 }
00236
00237 };
00238
00239 template<class M, class X, class Y>
00240 class ConstructionArgs<SeqILUn<M,X,Y> >
00241 : public DefaultConstructionArgs<SeqILUn<M,X,Y> >
00242 {
00243 public:
00244 ConstructionArgs(int n=1)
00245 : n_(n)
00246 {}
00247
00248 void setN(int n)
00249 {
00250 n_ = n;
00251 }
00252 int getN()
00253 {
00254 return n_;
00255 }
00256
00257 private:
00258 int n_;
00259 };
00260
00261
00265 template<class M, class X, class Y>
00266 struct ConstructionTraits<SeqILUn<M,X,Y> >
00267 {
00268 typedef ConstructionArgs<SeqILUn<M,X,Y> > Arguments;
00269
00270 static inline SeqILUn<M,X,Y>* construct(Arguments& args)
00271 {
00272 return new SeqILUn<M,X,Y>(args.getMatrix(), args.getN(),
00273 args.getArgs().relaxationFactor);
00274 }
00275
00276 static void deconstruct(SeqILUn<M,X,Y>* ilu)
00277 {
00278 delete ilu;
00279 }
00280
00281 };
00282
00286 template<class M, class X, class Y, class C>
00287 struct ConstructionTraits<ParSSOR<M,X,Y,C> >
00288 {
00289 typedef DefaultParallelConstructionArgs<M,C> Arguments;
00290
00291 static inline ParSSOR<M,X,Y,C>* construct(Arguments& args)
00292 {
00293 return new ParSSOR<M,X,Y,C>(args.getMatrix(), args.getArgs().iterations,
00294 args.getArgs().relaxationFactor,
00295 args.getComm());
00296 }
00297 static inline void deconstruct(ParSSOR<M,X,Y,C>* ssor)
00298 {
00299 delete ssor;
00300 }
00301 };
00302
00303 template<class X, class Y, class C, class T>
00304 struct ConstructionTraits<BlockPreconditioner<X,Y,C,T> >
00305 {
00306 typedef DefaultParallelConstructionArgs<T,C> Arguments;
00307 typedef ConstructionTraits<T> SeqConstructionTraits;
00308 static inline BlockPreconditioner<X,Y,C,T>* construct(Arguments& args)
00309 {
00310 return new BlockPreconditioner<X,Y,C,T>(*SeqConstructionTraits::construct(args),
00311 args.getComm());
00312 }
00313
00314 static inline void deconstruct(BlockPreconditioner<X,Y,C,T>* bp)
00315 {
00316 SeqConstructionTraits::deconstruct(static_cast<T*>(&bp->preconditioner));
00317 delete bp;
00318 }
00319
00320 };
00321
00332 template<class T>
00333 struct SmootherApplier
00334 {
00335 typedef T Smoother;
00336 typedef typename Smoother::range_type Range;
00337 typedef typename Smoother::domain_type Domain;
00338
00346 static void preSmooth(Smoother& smoother, Domain& v, const Range& d)
00347 {
00348 smoother.apply(v,d);
00349 }
00350
00358 static void postSmooth(Smoother& smoother, Domain& v, const Range& d)
00359 {
00360 smoother.apply(v,d);
00361 }
00362 };
00363
00364 template<class M, class X, class Y, int l>
00365 struct SmootherApplier<SeqSOR<M,X,Y,l> >
00366 {
00367 typedef SeqSOR<M,X,Y,l> Smoother;
00368 typedef typename Smoother::range_type Range;
00369 typedef typename Smoother::domain_type Domain;
00370
00371 static void preSmooth(Smoother& smoother, Domain& v, Range& d)
00372 {
00373 smoother.template apply<true>(v,d);
00374 }
00375
00376
00377 static void postSmooth(Smoother& smoother, Domain& v, Range& d)
00378 {
00379 smoother.template apply<false>(v,d);
00380 }
00381 };
00382 #ifdef HAVE_SUPERLU
00383 }
00384
00385
00386 template<class M, class X, class MO, bool b, class A>
00387 class SeqOverlappingSchwarz;
00388
00389 class MultiplicativeSchwarzMode;
00390
00391 namespace Amg
00392 {
00393 template<class M, class X, bool b, class TA>
00394 struct SmootherApplier<SeqOverlappingSchwarz<M,X,MultiplicativeSchwarzMode,b,TA> >
00395 {
00396 typedef SeqOverlappingSchwarz<M,X,MultiplicativeSchwarzMode,b,TA> Smoother;
00397 typedef typename Smoother::range_type Range;
00398 typedef typename Smoother::domain_type Domain;
00399
00400 static void preSmooth(Smoother& smoother, Domain& v, const Range& d)
00401 {
00402 smoother.template apply<true>(v,d);
00403 }
00404
00405
00406 static void postSmooth(Smoother& smoother, Domain& v, const Range& d)
00407 {
00408 smoother.template apply<false>(v,d);
00409
00410 }
00411 };
00412
00413
00414
00415
00416 template<class T>
00417 struct SeqOverlappingSchwarzSmootherArgs
00418 : public DefaultSmootherArgs<T>
00419 {
00420 enum Overlap {vertex, aggregate, pairwise, none};
00421
00422 Overlap overlap;
00423 SeqOverlappingSchwarzSmootherArgs(Overlap overlap_=vertex)
00424 : overlap(overlap)
00425 {}
00426 };
00427
00428 template<class M, class X, class TM, bool b, class TA>
00429 struct SmootherTraits<SeqOverlappingSchwarz<M,X,TM,b,TA> >
00430 {
00431 typedef SeqOverlappingSchwarzSmootherArgs<typename M::field_type> Arguments;
00432 };
00433
00434 template<class M, class X, class TM, bool b, class TA>
00435 class ConstructionArgs<SeqOverlappingSchwarz<M,X,TM,b,TA> >
00436 : public DefaultConstructionArgs<SeqOverlappingSchwarz<M,X,TM,b,TA> >
00437 {
00438 typedef DefaultConstructionArgs<SeqOverlappingSchwarz<M,X,TM,b,TA> > Father;
00439
00440 public:
00441 typedef typename MatrixGraph<M>::VertexDescriptor VertexDescriptor;
00442 typedef Dune::Amg::AggregatesMap<VertexDescriptor> AggregatesMap;
00443 typedef typename AggregatesMap::AggregateDescriptor AggregateDescriptor;
00444 typedef typename SeqOverlappingSchwarz<M,X,TM,b,TA>::subdomain_vector Vector;
00445 typedef typename Vector::value_type Subdomain;
00446
00447 virtual void setMatrix(const M& matrix, const AggregatesMap& amap)
00448 {
00449 Father::setMatrix(matrix);
00450
00451 std::vector<bool> visited(amap.noVertices(), false);
00452 typedef IteratorPropertyMap<std::vector<bool>::iterator,IdentityMap> VisitedMapType;
00453 VisitedMapType visitedMap(visited.begin());
00454
00455 MatrixGraph<const M> graph(matrix);
00456
00457 typedef SeqOverlappingSchwarzSmootherArgs<typename M::field_type> SmootherArgs;
00458
00459 switch(Father::getArgs().overlap){
00460 case SmootherArgs::vertex:
00461 {
00462 VertexAdder visitor(subdomains, amap);
00463 createSubdomains(matrix, graph, amap, visitor, visitedMap);
00464 }
00465 break;
00466 case SmootherArgs::pairwise:
00467 {
00468 createPairDomains(graph);
00469 }
00470 break;
00471 case SmootherArgs::aggregate:
00472 {
00473 AggregateAdder<VisitedMapType> visitor(subdomains, amap, graph, visitedMap);
00474 createSubdomains(matrix, graph, amap, visitor, visitedMap);
00475 }
00476 break;
00477 case SmootherArgs::none:
00478 NoneAdder visitor;
00479 createSubdomains(matrix, graph, amap, visitor, visitedMap);
00480 break;
00481 default:
00482 DUNE_THROW(NotImplemented, "This overlapping scheme is not supported!");
00483 }
00484 }
00485 void setMatrix(const M& matrix)
00486 {
00487 Father::setMatrix(matrix);
00488
00489
00490 AggregatesMap amap(matrix.N());
00491 VertexDescriptor v=0;
00492 for(typename AggregatesMap::iterator iter=amap.begin();
00493 iter!=amap.end(); ++iter)
00494 *iter=v++;
00495
00496 std::vector<bool> visited(amap.noVertices(), false);
00497 typedef IteratorPropertyMap<std::vector<bool>::iterator,IdentityMap> VisitedMapType;
00498 VisitedMapType visitedMap(visited.begin());
00499
00500 MatrixGraph<const M> graph(matrix);
00501
00502 typedef SeqOverlappingSchwarzSmootherArgs<typename M::field_type> SmootherArgs;
00503
00504 switch(Father::getArgs().overlap){
00505 case SmootherArgs::vertex:
00506 {
00507 VertexAdder visitor(subdomains, amap);
00508 createSubdomains(matrix, graph, amap, visitor, visitedMap);
00509 }
00510 break;
00511 case SmootherArgs::aggregate:
00512 {
00513 DUNE_THROW(NotImplemented, "Aggregate overlap is not supported yet");
00514
00515
00516
00517
00518 }
00519 break;
00520 case SmootherArgs::pairwise:
00521 {
00522 createPairDomains(graph);
00523 }
00524 break;
00525 case SmootherArgs::none:
00526 NoneAdder visitor;
00527 createSubdomains(matrix, graph, amap, visitor, visitedMap);
00528
00529 }
00530 }
00531
00532 const Vector& getSubDomains()
00533 {
00534 return subdomains;
00535 }
00536
00537 private:
00538 struct VertexAdder
00539 {
00540 VertexAdder(Vector& subdomains_, const AggregatesMap& aggregates_)
00541 : subdomains(subdomains_), max(-1), subdomain(-1), aggregates(aggregates_)
00542 {}
00543 template<class T>
00544 void operator()(const T& edge)
00545 {
00546 if(aggregates[edge.target()]!=AggregatesMap::ISOLATED)
00547 subdomains[subdomain].insert(edge.target());
00548 }
00549 int setAggregate(const AggregateDescriptor& aggregate_)
00550 {
00551 subdomain=aggregate_;
00552 max = std::max(subdomain, aggregate_);
00553 return subdomain;
00554 }
00555 int noSubdomains() const
00556 {
00557 return max+1;
00558 }
00559 private:
00560 Vector& subdomains;
00561 AggregateDescriptor max;
00562 AggregateDescriptor subdomain;
00563 const AggregatesMap& aggregates;
00564 };
00565 struct NoneAdder
00566 {
00567 template<class T>
00568 void operator()(const T& edge)
00569 {}
00570 int setAggregate(const AggregateDescriptor& aggregate_)
00571 {
00572 return -1;
00573 }
00574 int noSubdomains() const
00575 {
00576 return -1;
00577 }
00578 };
00579
00580 template<class VM>
00581 struct AggregateAdder
00582 {
00583 AggregateAdder(Vector& subdomains_, const AggregatesMap& aggregates_,
00584 const MatrixGraph<const M>& graph_, VM& visitedMap_)
00585 : subdomains(subdomains_), subdomain(-1), aggregates(aggregates_),
00586 adder(subdomains_, aggregates_), graph(graph_), visitedMap(visitedMap_)
00587 {}
00588 template<class T>
00589 void operator()(const T& edge)
00590 {
00591 subdomains[subdomain].insert(edge.target());
00592
00593
00594
00595 if(aggregates[edge.target()]!=AggregatesMap::ISOLATED){
00596 assert(aggregates[edge.target()]!=aggregate);
00597 typename AggregatesMap::VertexList vlist;
00598 aggregates.template breadthFirstSearch<true,false>(edge.target(), aggregate,
00599 graph, vlist, adder, adder,
00600 visitedMap);
00601 }
00602 }
00603
00604 int setAggregate(const AggregateDescriptor& aggregate_)
00605 {
00606 adder.setAggregate(aggregate_);
00607 aggregate=aggregate_;
00608 return ++subdomain;
00609 }
00610 int noSubdomains() const
00611 {
00612 return subdomain+1;
00613 }
00614
00615 private:
00616 AggregateDescriptor aggregate;
00617 Vector& subdomains;
00618 int subdomain;
00619 const AggregatesMap& aggregates;
00620 VertexAdder adder;
00621 const MatrixGraph<const M>& graph;
00622 VM& visitedMap;
00623 };
00624
00625 void createPairDomains(const MatrixGraph<const M>& graph)
00626 {
00627 typedef typename MatrixGraph<const M>::ConstVertexIterator VIter;
00628 typedef typename MatrixGraph<const M>::ConstEdgeIterator EIter;
00629 typedef typename M::size_type size_type;
00630
00631 std::set<std::pair<size_type,size_type> > pairs;
00632 int total=0;
00633 for(VIter v=graph.begin(), ve=graph.end(); ve != v; ++v)
00634 for(EIter e = v.begin(), ee=v.end(); ee!=e; ++e)
00635 {
00636 ++total;
00637 if(e.source()<e.target())
00638 pairs.insert(std::make_pair(e.source(),e.target()));
00639 else
00640 pairs.insert(std::make_pair(e.target(),e.source()));
00641 }
00642
00643
00644 subdomains.resize(pairs.size());
00645 std::cout <<std::endl<< "Created "<<pairs.size()<<" ("<<total<<") pair domains"<<std::endl<<std::endl;
00646 typedef typename std::set<std::pair<size_type,size_type> >::const_iterator SIter;
00647 typename Vector::iterator subdomain=subdomains.begin();
00648
00649 for(SIter s=pairs.begin(), se =pairs.end(); se!=s; ++s)
00650 {
00651 subdomain->insert(s->first);
00652 subdomain->insert(s->second);
00653 ++subdomain;
00654 }
00655 std::size_t minsize=10000;
00656 std::size_t maxsize=0;
00657 int sum=0;
00658 for(int i=0; i < subdomains.size(); ++i){
00659 sum+=subdomains[i].size();
00660 minsize=std::min(minsize, subdomains[i].size());
00661 maxsize=std::max(maxsize, subdomains[i].size());
00662 }
00663 std::cout<<"Subdomain size: min="<<minsize<<" max="<<maxsize<<" avg="<<(sum/subdomains.size())
00664 <<" no="<<subdomains.size()<<std::endl;
00665 }
00666
00667 template<class Visitor>
00668 void createSubdomains(const M& matrix, const MatrixGraph<const M>& graph,
00669 const AggregatesMap& amap, Visitor& overlapVisitor,
00670 IteratorPropertyMap<std::vector<bool>::iterator,IdentityMap>& visitedMap )
00671 {
00672
00673
00674
00675
00676 int isolated=0;
00677 AggregateDescriptor maxAggregate=0;
00678
00679 for(int i=0; i < amap.noVertices(); ++i)
00680 if(amap[i]==AggregatesMap::ISOLATED)
00681 isolated++;
00682 else
00683 maxAggregate = std::max(maxAggregate, amap[i]);
00684
00685 subdomains.resize(maxAggregate+1+isolated);
00686
00687
00688 for(int i=0; i < subdomains.size(); ++i)
00689 subdomains[i].clear();
00690
00691
00692
00693
00694 VertexAdder aggregateVisitor(subdomains, amap);
00695
00696 for(VertexDescriptor i=0; i < amap.noVertices(); ++i)
00697 if(!get(visitedMap, i)){
00698 AggregateDescriptor aggregate=amap[i];
00699
00700 if(amap[i]==AggregatesMap::ISOLATED){
00701
00702 subdomains.push_back(Subdomain());
00703 aggregate=subdomains.size()-1;
00704 }
00705 overlapVisitor.setAggregate(aggregate);
00706 aggregateVisitor.setAggregate(aggregate);
00707 subdomains[aggregate].insert(i);
00708 typename AggregatesMap::VertexList vlist;
00709 amap.template breadthFirstSearch<false,false>(i, aggregate, graph, vlist, aggregateVisitor,
00710 overlapVisitor, visitedMap);
00711 }
00712
00713 std::size_t minsize=10000;
00714 std::size_t maxsize=0;
00715 int sum=0;
00716 for(int i=0; i < subdomains.size(); ++i){
00717 sum+=subdomains[i].size();
00718 minsize=std::min(minsize, subdomains[i].size());
00719 maxsize=std::max(maxsize, subdomains[i].size());
00720 }
00721 std::cout<<"Subdomain size: min="<<minsize<<" max="<<maxsize<<" avg="<<(sum/subdomains.size())
00722 <<" no="<<subdomains.size()<<std::endl;
00723
00724
00725
00726 }
00727 Vector subdomains;
00728 };
00729
00730
00731 template<class M, class X, class TM, bool b, class TA>
00732 struct ConstructionTraits<SeqOverlappingSchwarz<M,X,TM,b,TA> >
00733 {
00734 typedef ConstructionArgs<SeqOverlappingSchwarz<M,X,TM,b,TA> > Arguments;
00735
00736 static inline SeqOverlappingSchwarz<M,X,TM,b,TA>* construct(Arguments& args)
00737 {
00738 return new SeqOverlappingSchwarz<M,X,TM,b,TA>(args.getMatrix(),
00739 args.getSubDomains(),
00740 args.getArgs().relaxationFactor);
00741 }
00742
00743 static void deconstruct(SeqOverlappingSchwarz<M,X,TM,b,TA>* schwarz)
00744 {
00745 delete schwarz;
00746 }
00747 };
00748
00749 #endif
00750 }
00751 }
00752
00753
00754
00755 #endif