smoother.hh

Go to the documentation of this file.
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   }// end namespace Amg
00384 
00385     // forward declarations
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     //    template<class M, class X, class TM, class TA>
00414     //    class SeqOverlappingSchwarz;
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         /* Create aggregates map where each aggregate is just one vertex. */
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           AggregateAdder<VisitedMapType> visitor(subdomains, amap, graph, visitedMap);
00516           createSubdomains(matrix, graph, amap, visitor, visitedMap);
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           // If we (the neighbouring vertex of the aggregate)
00593           // are not isolated, add the aggregate we belong to 
00594           // to the same subdomain using the OneOverlapAdder
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         // count  number ag aggregates. We asume that the
00673         // aggregates are numbered consecutively from 0 exept
00674         // for the isolated ones. All isolated vertices form 
00675         // one aggregate, here.
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         // reset the subdomains
00688         for(int i=0; i < subdomains.size(); ++i)
00689           subdomains[i].clear();
00690         
00691         // Create the subdomains from the aggregates mapping.
00692         // For each aggregate we mark all entries and the 
00693         // neighbouring vertices as belonging to the same subdomain
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               // isolated vertex gets its own aggregate
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   } // namespace Amg
00751 } // namespace Dune
00752 
00753 
00754 
00755 #endif
Generated on Sat Apr 24 11:13:47 2010 for dune-istl by  doxygen 1.6.3