kamg.hh

Go to the documentation of this file.
00001 #ifndef DUNE_AMG_KAMG_HH
00002 #define DUNE_AMG_KAMG_HH
00003 
00004 #include<dune/istl/preconditioners.hh>
00005 #include"amg.hh"
00006 
00007 namespace Dune
00008 {
00009   namespace Amg
00010   {
00011 
00026     template<class AMG>
00027     class KAmgTwoGrid
00028       : public Preconditioner<typename AMG::Domain,typename AMG::Range>
00029     {
00031       typedef typename AMG::Domain Domain;
00033       typedef typename AMG::Range Range;
00034     public:
00035 
00036       enum {
00038         category = AMG::category
00039       };
00040       
00048       KAmgTwoGrid(AMG& amg, InverseOperator<Domain,Range>* coarseSolver)
00049         : amg_(amg), coarseSolver_(coarseSolver)
00050       {}
00051       
00053       void pre(typename AMG::Domain& x, typename AMG::Range& b)
00054       {}
00055       
00057       void post(typename AMG::Domain& x)
00058       {}
00059 
00061       void apply(typename AMG::Domain& v, const typename AMG::Range& d)
00062       {
00063         *amg_.rhs = d;
00064         *amg_.lhs = v;
00065           // Copy data
00066         *amg_.update=0;
00067 
00068         amg_.presmooth();
00069         bool processFineLevel = 
00070           amg_.moveToCoarseLevel();
00071 
00072         if(processFineLevel){
00073           typename AMG::Range b=*amg_.rhs;
00074           typename AMG::Domain x=*amg_.update;
00075           InverseOperatorResult res;
00076           coarseSolver_->apply(x, b, res);
00077           *amg_.update=x;
00078         }
00079         
00080         amg_.moveToFineLevel(processFineLevel);
00081         
00082         amg_.postsmooth();
00083         v=*amg_.update;
00084       }
00085 
00090       InverseOperator<Domain,Range>* coarseSolver()
00091       {
00092         return coarseSolver_;
00093       }
00094       
00096       ~KAmgTwoGrid()
00097       {}
00098       
00099     private:
00101       AMG& amg_;
00103       InverseOperator<Domain,Range>* coarseSolver_;
00104     };
00105     
00106 
00107 
00118     template<class M, class X, class S, class PI=SequentialInformation,
00119              class K=BiCGSTABSolver<X>, class A=std::allocator<X> >
00120     class KAMG : public Preconditioner<X,X>
00121     {
00122     public:
00124       typedef AMG<M,X,S,PI,A> Amg;
00126       typedef K KrylovSolver;
00128       typedef typename Amg::OperatorHierarchy OperatorHierarchy;
00130       typedef typename Amg::CoarseSolver CoarseSolver;
00132       typedef typename Amg::ParallelInformation ParallelInformation;
00134       typedef typename Amg::SmootherArgs SmootherArgs;
00136       typedef typename Amg::Operator Operator;
00138       typedef typename Amg::Domain Domain;
00140       typedef typename Amg::Range Range;
00142       typedef typename Amg::ParallelInformationHierarchy ParallelInformationHierarchy;
00144       typedef typename Amg::ScalarProduct ScalarProduct;
00145       
00146       enum {
00148         category = Amg::category
00149       };
00161       KAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, 
00162            const SmootherArgs& smootherArgs, std::size_t gamma,
00163            std::size_t preSmoothingSteps =1, std::size_t postSmoothingSteps = 1,
00164            std::size_t maxLevelKrylovSteps = 3 , double minDefectReduction =1e-1);
00165 
00182       template<class C>
00183       KAMG(const Operator& fineOperator, const C& criterion,
00184            const SmootherArgs& smootherArgs, std::size_t gamma=1,
00185            std::size_t preSmoothingSteps=1, std::size_t postSmoothingSteps=1,
00186            std::size_t maxLevelKrylovSteps=3, double minDefectReduction=1e-1,
00187            const ParallelInformation& pinfo=ParallelInformation());
00188 
00190       void pre(Domain& x, Range& b);
00192       void post(Domain& x);
00194       void apply(Domain& x, const Range& b);
00195 
00196       std::size_t maxlevels();
00197       
00198     private:
00200       Amg amg;
00201       
00203       std::size_t maxLevelKrylovSteps;
00204 
00206       double levelDefectReduction;
00207       
00209       std::vector<typename Amg::ScalarProduct*> scalarproducts;
00210       
00212       std::vector<KAmgTwoGrid<Amg>*> ksolvers;
00213     };
00214     
00215     template<class M, class X, class S, class P, class K, class A>
00216     KAMG<M,X,S,P,K,A>::KAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver, 
00217                             const SmootherArgs& smootherArgs,
00218                             std::size_t gamma, std::size_t preSmoothingSteps,
00219                             std::size_t postSmoothingSteps,
00220                             std::size_t ksteps, double reduction)
00221       : amg(matrices, coarseSolver, smootherArgs, gamma, preSmoothingSteps,
00222             postSmoothingSteps), maxLevelKrylovSteps(ksteps), levelDefectReduction(reduction)
00223     {}
00224     
00225     template<class M, class X, class S, class P, class K, class A>
00226       template<class C>
00227     KAMG<M,X,S,P,K,A>::KAMG(const Operator& fineOperator, const C& criterion,
00228                             const SmootherArgs& smootherArgs, std::size_t gamma,
00229                             std::size_t preSmoothingSteps, std::size_t postSmoothingSteps,
00230                             std::size_t ksteps, double reduction,
00231                             const ParallelInformation& pinfo)
00232       : amg(fineOperator, criterion, smootherArgs, gamma, preSmoothingSteps,
00233             postSmoothingSteps, false, pinfo), maxLevelKrylovSteps(ksteps), levelDefectReduction(reduction)
00234     {}
00235 
00236     
00237     template<class M, class X, class S, class P, class K, class A>
00238     void KAMG<M,X,S,P,K,A>::pre(Domain& x, Range& b)
00239     {
00240       amg.pre(x,b);
00241       scalarproducts.reserve(amg.levels());
00242       ksolvers.reserve(amg.levels());
00243 
00244       typename OperatorHierarchy::ParallelMatrixHierarchy::Iterator
00245         matrix = amg.matrices_->matrices().coarsest();
00246       typename ParallelInformationHierarchy::Iterator 
00247         pinfo = amg.matrices_->parallelInformation().coarsest();      
00248       bool hasCoarsest=(amg.levels()==amg.maxlevels());
00249       KrylovSolver* ks=0;
00250 
00251       if(hasCoarsest){
00252         if(matrix==amg.matrices_->matrices().finest())
00253         return;
00254         --matrix;
00255         --pinfo;
00256         ksolvers.push_back(new KAmgTwoGrid<Amg>(amg, amg.solver_));
00257       }else
00258         ksolvers.push_back(new KAmgTwoGrid<Amg>(amg, ks));
00259 
00260       std::ostringstream s;
00261       
00262       if(matrix!=amg.matrices_->matrices().finest())
00263         while(true){
00264           scalarproducts.push_back(Amg::ScalarProductChooser::construct(*pinfo));
00265           ks = new KrylovSolver(*matrix, *(scalarproducts.back()), 
00266                                 *(ksolvers.back()), levelDefectReduction, 
00267                                 maxLevelKrylovSteps, 0);
00268           ksolvers.push_back(new KAmgTwoGrid<Amg>(amg, ks)); 
00269           --matrix;
00270           --pinfo;
00271           if(matrix==amg.matrices_->matrices().finest())
00272             break;
00273         }
00274     }
00275     
00276     
00277     template<class M, class X, class S, class P, class K, class A>
00278     void KAMG<M,X,S,P,K,A>::post(Domain& x)
00279     {
00280       typedef typename std::vector<KAmgTwoGrid<Amg>*>::reverse_iterator KIterator;
00281       typedef typename std::vector<ScalarProduct*>::iterator SIterator;
00282       for(KIterator kiter = ksolvers.rbegin(); kiter != ksolvers.rend();
00283           ++kiter)
00284         {
00285           if((*kiter)->coarseSolver()!=amg.solver_)
00286             delete (*kiter)->coarseSolver();
00287           delete *kiter;
00288         }
00289       for(SIterator siter = scalarproducts.begin(); siter!=scalarproducts.end();
00290           ++siter)
00291         delete *siter;
00292       amg.post(x);
00293       
00294     }
00295 
00296     template<class M, class X, class S, class P, class K, class A>
00297     void KAMG<M,X,S,P,K,A>::apply(Domain& x, const Range& b)
00298     {
00299       amg.initIteratorsWithFineLevel();
00300       if(ksolvers.size()==0)
00301         {
00302           Range tb=b;
00303           InverseOperatorResult res;
00304           amg.solver_->apply(x,tb,res);
00305         }else
00306         ksolvers.back()->apply(x,b);
00307     }
00308 
00309     template<class M, class X, class S, class P, class K, class A>
00310     std::size_t KAMG<M,X,S,P,K,A>::maxlevels()
00311     {
00312       return amg.maxlevels();
00313     }
00314     
00316   } // Amg
00317 } // Dune
00318 
00319 #endif

Generated on Fri Apr 29 2011 with Doxygen (ver 1.7.1) [doxygen-log,error-log].