- Home
- About DUNE
- Download
- Documentation
- Community
- Development
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].