00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011
00012
00013
00014
00015 #ifndef _MULTIGRID_H_
00016 #define _MULTIGRID_H_
00017
00018 #include "CH_Timer.H"
00019 #include "LinearSolver.H"
00020 #include "ProblemDomain.H"
00021 #include "REAL.H"
00022 #include "Box.H"
00023 #include "parstream.H"
00024 #include "NamespaceHeader.H"
00025
00027
00031 template <class T>
00032 class MGLevelOp : public LinearOp<T>
00033 {
00034 public:
00036
00038 virtual ~MGLevelOp(){;}
00039
00041
00046 virtual void createCoarser(T& a_coarse, const T& a_fine, bool ghosted) = 0;
00047
00049
00055 virtual void relax(T& a_correction, const T& a_residual, int a_iterations) = 0 ;
00056
00057
00059
00063 virtual void restrictResidual(T& a_resCoarse, T& a_phiFine, const T& a_rhsFine) = 0;
00064
00066
00070 virtual void prolongIncrement(T& a_phiThisLevel, const T& a_correctCoarse) = 0;
00071
00072 };
00073
00075
00078 template <class T>
00079 class MGLevelOpFactory
00080 {
00081 public:
00082 virtual ~MGLevelOpFactory(){;}
00083
00085
00090 virtual MGLevelOp<T>* MGnewOp(const ProblemDomain& a_FineindexSpace,
00091 int a_depth,
00092 bool a_homoOnly = true) = 0;
00093 };
00094
00095
00097
00102 template <class T>
00103 class MultiGrid
00104 {
00105 public:
00106 MultiGrid();
00107 virtual ~MultiGrid();
00108
00110
00118 virtual void define(MGLevelOpFactory<T>& a_factory,
00119 LinearSolver<T>* a_bottomSolver,
00120 const ProblemDomain& a_domain,
00121 int a_maxDepth = -1);
00122
00124
00130 virtual void solve(T& a_phi, const T& a_rhs, Real a_tolerance, int a_maxIterations, int verbosity= 0);
00131
00133
00140 virtual void oneCycle(T& a_e, const T& a_res);
00141
00142
00143
00144 void init(const T& a_correction, const T& a_residual);
00145
00146
00147 void cycle(int a_depth, T& a_correction, const T& a_residual);
00148
00149
00150 void clear();
00151
00152
00153 void setBottomSolver(LinearSolver<T>* a_bottomSolver);
00154
00156
00162 int m_depth, m_defaultDepth, m_pre, m_post, m_bottom, m_cycle, m_numMG;
00163 bool m_homogeneous;
00164 LinearSolver<T>* m_bottomSolver;
00165
00167
00170 Vector< MGLevelOp<T>* > getAllOperators();
00171
00172 protected:
00173 bool m_defined;
00174
00175 int m_bottomCells;
00176
00177 ProblemDomain m_topLevelDomain;
00178 Vector<MGLevelOp<T>*> m_op;
00179 Vector< T* > m_residual;
00180 Vector< T* > m_correction;
00181 private:
00182 MultiGrid(const MultiGrid<T>& a_opin)
00183 {
00184 MayDay::Error("invalid operator");
00185 }
00186
00187 void operator=(const MultiGrid<T>& a_opin)
00188 {
00189 MayDay::Error("invalid operator");
00190 }
00191 };
00192
00193
00194
00195
00196
00197 template <class T>
00198 Vector< MGLevelOp<T>* >
00199 MultiGrid<T>::getAllOperators()
00200 {
00201 Vector<MGLevelOp<T>*> retval = m_op;
00202 return retval;
00203 }
00204
00205 template <class T>
00206 MultiGrid<T>::MultiGrid():
00207 m_pre(3), m_post(3), m_bottom(0), m_cycle(1), m_numMG(1), m_homogeneous(true),
00208 m_defined(false){;}
00209
00210 template <class T>
00211 MultiGrid<T>::~MultiGrid()
00212 {
00213 clear();
00214 }
00215
00216 template <class T>
00217 void MultiGrid<T>::define(MGLevelOpFactory<T>& a_factory,
00218 LinearSolver<T>* a_bottomSolver,
00219 const ProblemDomain& a_domain,
00220 int a_maxDepth)
00221 {
00222
00223 CH_TIME("MultiGrid::define");
00224 m_depth = 0;
00225 m_bottomSolver = a_bottomSolver;
00226 m_residual.resize(m_depth);
00227 m_correction.resize(m_depth);
00228 m_op.resize(m_depth);
00229 m_topLevelDomain = a_domain;
00230
00231 m_bottomCells = a_domain.domainBox().numPts();
00232
00233 MGLevelOp<T>* nextOp = a_factory.MGnewOp(a_domain, 0, true);
00234 while(nextOp != NULL)
00235 {
00236 m_residual.push_back(new T());
00237 m_correction.push_back(new T());
00238 m_op.push_back(nextOp);
00239 m_depth++;
00240 if((m_depth < a_maxDepth) || (a_maxDepth < 0))
00241 {
00242 nextOp = a_factory.MGnewOp(a_domain , m_depth, true);
00243 if(nextOp != NULL)
00244 for(int i=0; i<CH_SPACEDIM; ++i) m_bottomCells /= 2;
00245 }
00246 else
00247 {
00248 nextOp = NULL;
00249 }
00250 }
00251 m_defaultDepth = m_depth;
00252 m_bottomSolver->define(m_op[m_depth-1], true);
00253 m_defined = true;
00254 }
00255
00256 template <class T>
00257 void MultiGrid<T>::setBottomSolver(LinearSolver<T>* a_bottomSolver)
00258 {
00259 m_bottomSolver = a_bottomSolver;
00260 m_bottomSolver->define(m_op[m_depth-1], true);
00261 }
00262
00263 template <class T>
00264 void MultiGrid<T>::init(const T& a_e, const T& a_residual)
00265 {
00266 CH_TIME("MutliGrid::init");
00267 if (m_depth > 1)
00268 {
00269 m_op[0]->createCoarser(*(m_residual[1]), a_residual, false);
00270 m_op[0]->createCoarser(*(m_correction[1]), a_e, true);
00271 }
00272
00273 for (int i = 2; i < m_depth; i++)
00274 {
00275 m_op[i-1]->createCoarser(*(m_residual[i]), *(m_residual[i-1]), false);
00276 m_op[i-1]->createCoarser(*(m_correction[i]), *(m_correction[i-1]), true);
00277 }
00278 }
00279
00280 template <class T>
00281 void MultiGrid<T>::solve(T& a_phi, const T& a_rhs, Real a_tolerance, int a_maxIterations, int verbosity)
00282 {
00283 CH_TIME("MultiGrid::solve");
00284 this->init(a_phi, a_rhs);
00285
00286 T correction, residual;
00287 m_op[0]->create(correction, a_phi);
00288 m_op[0]->create(residual, a_rhs);
00289 m_op[0]->setToZero(a_phi);
00290 m_op[0]->residual(residual, a_phi, a_rhs, false);
00291
00292 Real errorno = m_op[0]->norm(residual, 0);
00293 if(verbosity > 2)
00294 {
00295 pout() << "multigrid::solve initial residual = " << errorno << std::endl;
00296 }
00297 Real compval = a_tolerance*errorno;
00298 Real epsilon = 1.0e-16;
00299 compval = Max(compval, epsilon);
00300 Real error = errorno;
00301 int iter = 0;
00302 while((error > compval) && (error > a_tolerance*errorno) && (iter < a_maxIterations))
00303 {
00304 m_op[0]->setToZero(correction);
00305 m_op[0]->residual(residual, a_phi, a_rhs, false);
00306 error = m_op[0]->norm(residual, 0);
00307 if(verbosity > 3)
00308 {
00309 pout() << "multigrid::solve iter = " << iter << ", residual = " << error << std::endl;
00310 }
00311
00312 this->cycle(0, correction, residual);
00313 m_op[0]->incr(a_phi, correction, 1.0);
00314
00315 iter++;
00316 }
00317 if(verbosity > 2)
00318 {
00319 pout() << "multigrid::solve final residual = " << error << std::endl;
00320 }
00321
00322 m_op[0]->clear(correction);
00323 m_op[0]->clear(residual);
00324 }
00325
00326 template <class T>
00327 void MultiGrid<T>::oneCycle(T& a_e, const T& a_residual)
00328 {
00329
00330 if (m_homogeneous)
00331 {
00332 cycle(0, a_e, a_residual);
00333 }
00334 else
00335 {
00336 T correction, residual;
00337 m_op[0]->create(correction, a_e);
00338 m_op[0]->create(residual, a_residual);
00339
00340 m_op[0]->residual(residual, a_e, a_residual);
00341
00342 m_op[0]->setToZero(correction);
00343 this->cycle(0, correction, residual);
00344
00345 m_op[0]->incr(a_e, correction, 1.0);
00346 m_op[0]->clear(correction);
00347 m_op[0]->clear(residual);
00348 }
00349 }
00350
00351 template <class T>
00352 void MultiGrid<T>::cycle(int depth, T& correction, const T& residual)
00353 {
00354
00355
00356 if(depth == m_depth-1)
00357 {
00358 if(m_bottomCells == 1)
00359 {
00360 m_op[depth ]->relax(correction, residual, 1);
00361 }
00362 else
00363 {
00364 m_op[depth ]->relax(correction, residual, m_bottom);
00365 m_bottomSolver->solve(correction, residual);
00366 }
00367 }
00368 else
00369 {
00370 int cycles = m_cycle;
00371 if( cycles < 0 )
00372 {
00373 cycles = -cycles;
00374
00375 m_op[depth ]->restrictResidual(*(m_residual[depth+1]), correction, residual);
00376 m_op[depth ]->setToZero(*(m_correction[depth+1]));
00377
00378
00379 cycle(depth+1, *(m_correction[depth+1]), *(m_residual[depth+1]));
00380
00381 m_op[depth ]->prolongIncrement(correction, *(m_correction[depth+1]));
00382
00383 m_op[depth ]->relax(correction, residual, m_pre);
00384
00385 for(int img = 0; img < cycles; img++)
00386 {
00387 m_op[depth ]->restrictResidual(*(m_residual[depth+1]), correction, residual);
00388 m_op[depth ]->setToZero(*(m_correction[depth+1]));
00389
00390 m_cycle = 1;
00391 cycle(depth+1, *(m_correction[depth+1]), *(m_residual[depth+1]));
00392 m_cycle = -cycles;
00393
00394 m_op[depth ]->prolongIncrement(correction, *(m_correction[depth+1]));
00395 }
00396
00397 m_op[depth ]->relax(correction, residual, m_post);
00398 }
00399 else
00400 {
00401 m_op[depth ]->relax( correction, residual, m_pre );
00402
00403 m_op[depth ]->restrictResidual(*(m_residual[depth+1]), correction, residual);
00404 m_op[depth ]->setToZero(*(m_correction[depth+1]));
00405
00406 for(int img = 0; img < cycles; img++)
00407 {
00408 cycle(depth+1, *(m_correction[depth+1]), *(m_residual[depth+1]));
00409 if(depth+1 == m_depth-1) break;
00410 }
00411 m_op[depth ]->prolongIncrement(correction, *(m_correction[depth+1]));
00412
00413 m_op[depth ]->relax(correction, residual, m_post);
00414 }
00415 }
00416 }
00417
00418 template <class T>
00419 void MultiGrid<T>::clear()
00420 {
00421 for(int i=0; i<m_op.size(); ++i)
00422 {
00423 delete m_op[i];
00424 delete m_correction[i];
00425 delete m_residual[i];
00426 }
00427 m_op.resize(0);
00428 m_residual.resize(0);
00429 m_correction.resize(0);
00430 m_defined = false;
00431 }
00432
00433 #include "NamespaceFooter.H"
00434 #endif