00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011
00012
00013
00014
00015 #ifndef _AMRMULTIGRID_H_
00016 #define _AMRMULTIGRID_H_
00017
00018 #include "MultiGrid.H"
00019 #include "REAL.H"
00020 #include "Box.H"
00021 #include "NoOpSolver.H"
00022 #include "parstream.H"
00023 #include "CH_Timer.H"
00024 #include "Copier.H"
00025 #include "SPMD.H"
00026 #include "Misc.H"
00027
00028 #include "NamespaceHeader.H"
00029
00031
00034 template <class T>
00035 class AMRLevelOp : public MGLevelOp<T>
00036 {
00037 public:
00038
00039 virtual ~AMRLevelOp(){;}
00040
00041 virtual Real AMRNorm(const T& a_coarResid,
00042 const T& a_fineResid,
00043 const int& a_refRat,
00044 const int& a_ord)
00045 { return this->norm(a_coarResid, 0);}
00046
00048
00052 virtual int refToCoarser() = 0;
00053
00055
00058 virtual void AMRResidual(T& a_residual, const T& a_phiFine, const T& a_phi,
00059 const T& a_phiCoarse, const T& a_rhs,
00060 bool a_homogeneousDomBC,
00061 AMRLevelOp<T>* a_finerOp) = 0;
00062
00064
00068 virtual void AMRResidualNF(T& a_residual, const T& a_phi, const T& a_phiCoarse,
00069 const T& a_rhs, bool a_homogeneousBC) = 0;
00070
00072
00076 virtual void AMRResidualNC(T& a_residual, const T& a_phiFine, const T& a_phi,
00077 const T& a_rhs, bool a_homogeneousBC,
00078 AMRLevelOp<T>* a_finerOp) = 0;
00079
00080
00081
00083
00086 virtual void AMROperator(T& a_LofPhi,
00087 const T& a_phiFine, const T& a_phi,
00088 const T& a_phiCoarse,
00089 bool a_homogeneousDomBC,
00090 AMRLevelOp<T>* a_finerOp) = 0;
00091
00093
00097 virtual void AMROperatorNF(T& a_LofPhi,
00098 const T& a_phi,
00099 const T& a_phiCoarse,
00100 bool a_homogeneousBC) = 0;
00101
00103
00107 virtual void AMROperatorNC(T& a_LofPhi,
00108 const T& a_phiFine,
00109 const T& a_phi,
00110 bool a_homogeneousBC,
00111 AMRLevelOp<T>* a_finerOp) = 0;
00112
00113
00115
00116 virtual void AMRRestrict(T& a_resCoarse, const T& a_residual, const T& a_correction,
00117 const T& a_coarseCorrection) = 0;
00118
00119
00120
00122
00123 virtual void AMRProlong(T& a_correction, const T& a_coarseCorrection) = 0;
00124
00125
00126
00128
00129 virtual void AMRUpdateResidual(T& a_residual, const T& a_correction,
00130 const T& a_coarseCorrection) = 0;
00131
00132
00134
00136 virtual void createCoarsened(T& a_lhs,
00137 const T& a_rhs,
00138 const int& a_refRat) = 0;
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 virtual void buildCopier(Copier& a_copier, const T& a_lhs, const T& a_rhs)
00152 {;}
00153
00154 virtual void assignCopier(T& a_lhs, const T& a_rhs, const Copier& a_copier)
00155 {
00156 this->assign(a_lhs, a_rhs);
00157 }
00158
00159 virtual void zeroCovered(T& a_lhs, T& a_rhs, const Copier& a_copier)
00160 {
00161 this->setToZero(a_rhs);
00162 this->assignCopier(a_lhs, a_rhs, a_copier);
00163 }
00164 virtual Real localMaxNorm(const T& a_phi) { return this->norm(a_phi, 0);}
00165
00167 virtual void AMRProlongS(T& a_correction, const T& a_coarseCorrection,
00168 T& a_temp, const Copier& a_copier)
00169 {
00170 AMRProlong(a_correction, a_coarseCorrection);
00171 }
00172 virtual void AMRRestrictS(T& a_resCoarse, const T& a_residual, const T& a_correction,
00173 const T& a_coarseCorrection, T& scratch)
00174 {
00175 AMRRestrict(a_resCoarse, a_residual, a_correction, a_coarseCorrection);
00176 }
00177
00178 };
00179
00181
00184 template <class T>
00185 class AMRLevelOpFactory : public MGLevelOpFactory<T>
00186 {
00187 public:
00188 virtual ~AMRLevelOpFactory(){;}
00189
00191
00195 virtual AMRLevelOp<T>* AMRnewOp(const ProblemDomain& a_indexSpace)=0;
00196
00198
00201 virtual int refToFiner(const ProblemDomain& a_indexSpace) const =0;
00202
00203 };
00204
00206
00209 template <class T>
00210 class AMRMultiGrid
00211 {
00212 public:
00213
00214 AMRMultiGrid();
00215
00216 virtual ~AMRMultiGrid();
00217
00219
00226 virtual void define(const ProblemDomain& a_coarseDomain,
00227 AMRLevelOpFactory<T>& a_factory,
00228 LinearSolver<T>* a_bottomSolver,
00229 int a_numLevels);
00230
00232
00236 virtual void solve(Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00237 int l_max, int l_base, bool a_zeroPhi=true);
00238
00240
00243 virtual void solveNoInit(Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00244 int l_max, int l_base, bool a_zeroPhi=true);
00245
00246 void relaxOnlyHomogeneous(Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00247 int l_max, int l_base);
00248
00249 virtual void AMRVCycle(Vector<T*>& a_correction,
00250 Vector<T*>& a_residual,
00251 int l, int l_max, int l_base);
00252
00253 void setMGCycle(int a_numMG);
00254
00255 void init(const Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00256 int l_max, int l_base);
00257
00258 void revert(const Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00259 int l_max, int l_base);
00260
00261
00262 Real m_eps, m_hang, m_normThresh;
00263 bool m_solverParamsSet;
00264 int m_imin, m_iterMax, m_verbosity, m_exitStatus;
00265 int m_pre, m_post, m_bottom, m_numMG;
00267
00269 int m_maxDepth;
00270 AMRLevelOp<T>& levelOp(int level);
00271
00272
00273
00274
00275 Real m_convergenceMetric;
00276
00278
00281 Real computeAMRResidual(Vector<T*>& a_resid,
00282 Vector<T*>& a_phi,
00283 const Vector<T*>& a_rhs,
00284 int l_max,
00285 int l_base,
00286 bool a_homogeneousBC=false,
00287 bool a_computeNorm=true);
00288
00290
00293 void computeAMROperator(Vector<T*>& a_lph,
00294 Vector<T*>& a_phi,
00295 int l_max,
00296 int l_base,
00297 bool a_homogeneousBC=false);
00298
00300
00303 Vector< MGLevelOp<T>* > getAllOperators();
00304 Vector< MGLevelOp<T>* > getOperatorsOp();
00305 Vector< Vector< MGLevelOp<T>* > > getOperatorsMG();
00306
00308
00319 void setSolverParameters(const int& a_pre,
00320 const int& a_post,
00321 const int& a_bottom,
00322 const int& a_numMG,
00323 const int& a_iterMax,
00324 const Real& a_eps,
00325 const Real& a_hang,
00326 const Real& a_normThresh);
00327
00328
00330
00335 void setBottomSolver(int l_max, int l_base);
00336
00337 protected:
00338
00339 void relax(T& phi, T& R, int depth, int nRelax = 2);
00340
00341 void computeAMRResidualLevel(Vector<T*>& a_resid,
00342 Vector<T*>& a_phi,
00343 const Vector<T*>& a_rhs,
00344 int l_max, int l_base, int ilev,
00345 bool a_homogeneousBC);
00346
00347 Vector<AMRLevelOp<T>*> m_op;
00348 Vector<MultiGrid<T> *> m_mg;
00349 Vector<T*> m_correction;
00350 Vector<T*> m_residual;
00351 Vector<T*> m_resC;
00352 Vector<Copier> m_resCopier;
00353 Vector<Copier> m_reverseCopier;
00354
00355 NoOpSolver<T> m_nosolve;
00356
00357 LinearSolver<T>* m_bottomSolver;
00358
00359 void clear();
00360
00361 private:
00362 AMRMultiGrid(const AMRMultiGrid<T>& a_opin)
00363 {
00364 MayDay::Error("invalid operator");
00365 }
00366
00367 void operator=(const AMRMultiGrid<T>& a_opin)
00368 {
00369 MayDay::Error("invalid operator");
00370 }
00371 };
00372
00373
00374
00375
00376
00377
00378
00379 template <class T>
00380 void
00381 AMRMultiGrid<T>::setSolverParameters(const int& a_pre,
00382 const int& a_post,
00383 const int& a_bottom,
00384 const int& a_numMG,
00385 const int& a_iterMax,
00386 const Real& a_eps,
00387 const Real& a_hang,
00388 const Real& a_normThresh)
00389 {
00390 m_solverParamsSet = true;
00391 m_pre = a_pre;
00392 m_post = a_post;
00393 m_bottom = a_bottom;
00394 m_eps = a_eps;
00395 m_hang = a_hang;
00396 m_normThresh = a_normThresh;
00397 m_iterMax = a_iterMax;
00398 for (int img = 0; img < m_mg.size(); img++)
00399 {
00400 m_mg[img]->m_pre = a_pre;
00401 m_mg[img]->m_post = a_post;
00402 m_mg[img]->m_bottom = a_bottom;
00403 }
00404 setMGCycle(a_numMG);
00405 }
00406 template <class T>
00407 Vector< MGLevelOp<T> * >
00408 AMRMultiGrid<T>::getAllOperators()
00409 {
00410 Vector< MGLevelOp<T>* > retval;
00411 for (int iop = 0; iop < m_op.size(); iop++)
00412 {
00413 MGLevelOp<T>* operPtr = (MGLevelOp<T>*) m_op[iop];
00414 retval.push_back(operPtr);
00415 }
00416
00417 for (int img = 0; img < m_mg.size(); img++)
00418 {
00419 Vector< MGLevelOp<T>* > mgOps = m_mg[img]->getAllOperators();
00420 retval.append(mgOps);
00421 }
00422 return retval;
00423 }
00424
00425 template <class T>
00426 Vector< MGLevelOp<T> * >
00427 AMRMultiGrid<T>::getOperatorsOp()
00428 {
00429 Vector< MGLevelOp<T>* > retval;
00430 for (int iop = 0; iop < m_op.size(); iop++)
00431 {
00432 MGLevelOp<T>* operPtr = (MGLevelOp<T>*) m_op[iop];
00433 retval.push_back(operPtr);
00434 }
00435 return retval;
00436 }
00437
00438 template <class T>
00439 Vector<Vector< MGLevelOp<T> * > >
00440 AMRMultiGrid<T>::getOperatorsMG()
00441 {
00442 Vector< Vector< MGLevelOp<T>* > > retval(m_mg.size());
00443
00444 for (int img = 0; img < m_mg.size(); img++)
00445 {
00446 retval[img] = m_mg[img]->getAllOperators();
00447 }
00448 return retval;
00449 }
00450
00451 template <class T>
00452 AMRMultiGrid<T>::AMRMultiGrid():m_eps(1E-6), m_hang(1E-15), m_normThresh(1E-30),
00453 m_imin(5), m_iterMax(20), m_verbosity(3),
00454 m_pre(2), m_post(2), m_bottom(2),
00455 m_numMG(1), m_maxDepth(-1),
00456 m_convergenceMetric(0.),
00457 m_bottomSolver(NULL)
00458 {
00459 m_solverParamsSet = false;
00460 }
00461 template <class T>
00462 void AMRMultiGrid<T>::setMGCycle(int a_numMG)
00463 {
00464 for (int ilev = 0; ilev < m_op.size(); ilev++)
00465 {
00466 m_mg[ilev]->m_numMG = a_numMG;
00467 m_mg[ilev]->m_cycle = a_numMG;
00468 }
00469 m_numMG = a_numMG;
00470 }
00471 template <class T>
00472 void AMRMultiGrid<T>::relax(T& a_correction, T& a_residual, int depth, int a_numSmooth)
00473 {
00474 CH_TIME("AMRMultiGrid::relax");
00475 m_op[depth]->relax(a_correction, a_residual, a_numSmooth);
00476
00477 if (m_op[depth]->refToCoarser() > 2)
00478 {
00479 int intermediateDepth = 0;
00480 int r = m_op[depth]->refToCoarser();
00481 while(r>2)
00482 {
00483 r/=2;
00484 intermediateDepth++;
00485 }
00486 int tmp = m_mg[depth]->m_depth;
00487 m_mg[depth]->m_depth = intermediateDepth;
00488
00489
00490 m_mg[depth]->cycle(0, a_correction, a_residual);
00491 m_mg[depth]->m_depth = tmp;
00492 }
00493 }
00494
00495 template <class T>
00496 AMRMultiGrid<T>::~AMRMultiGrid()
00497 {
00498 CH_TIME("~AMRMultiGrid");
00499 clear();
00500 }
00501
00502 template <class T>
00503 AMRLevelOp<T>& AMRMultiGrid<T>::levelOp(int level)
00504 {
00505 return *(m_op[level]);
00506 }
00507
00508
00509 template <class T>
00510 Real AMRMultiGrid<T>::computeAMRResidual(Vector<T*>& a_resid,
00511 Vector<T*>& a_phi,
00512 const Vector<T*>& a_rhs,
00513 int l_max,
00514 int l_base,
00515 bool a_homogeneousBC,
00516 bool a_computeNorm)
00517 {
00518 CH_TIME("AMRMultiGrid::computeAMRResidual");
00519
00520 Real rnorm = 0;
00521 Real localNorm = 0;
00522 for (int ilev = l_base; ilev <= l_max; ilev++)
00523 {
00524
00525 computeAMRResidualLevel(a_resid,
00526 a_phi,
00527 a_rhs,
00528 l_max, l_base, ilev, a_homogeneousBC);
00529 if (a_computeNorm){
00530 if (ilev == l_max)
00531 {
00532 localNorm =m_op[ilev]->localMaxNorm(*a_resid[ilev]);
00533 }
00534 else
00535 {
00536
00537
00538 m_op[ilev]->zeroCovered(*a_resid[ilev], *m_resC[ilev+1], m_resCopier[ilev+1]);
00539 localNorm = m_op[ilev]->localMaxNorm(*a_resid[ilev]);
00540 }
00541 }
00542 rnorm = Max(localNorm, rnorm);
00543 }
00544 #ifdef CH_MPI
00545 if (a_computeNorm){
00546 CH_TIME("MPI_Allreduce");
00547 Real recv;
00548 int result = MPI_Allreduce(&rnorm, &recv, 1, MPI_CH_REAL,
00549 MPI_MAX, Chombo_MPI::comm);
00550 if (result != MPI_SUCCESS){
00551 MayDay::Error("sorry, but I had a communcation error on norm");
00552 }
00553 rnorm = recv;
00554 }
00555 #endif
00556
00557 return rnorm;
00558 }
00559
00560
00561
00562 template <class T>
00563 void AMRMultiGrid<T>::computeAMROperator(Vector<T*>& a_lph,
00564 Vector<T*>& a_phi,
00565 int l_max,
00566 int l_base,
00567 bool a_homogeneousBC)
00568 {
00569 for (int ilev = l_base; ilev <= l_max; ilev++)
00570 {
00571 m_op[ilev]->create(*m_residual[ilev], *a_lph[ilev]);
00572 m_op[ilev]->setToZero(*m_residual[ilev]);
00573 }
00574 computeAMRResidual(a_lph, a_phi, m_residual, l_max, l_base, a_homogeneousBC, false);
00575 }
00576
00577 template <class T>
00578 void AMRMultiGrid<T>::computeAMRResidualLevel(Vector<T*>& a_resid,
00579 Vector<T*>& a_phi,
00580 const Vector<T*>& a_rhs,
00581 int l_max, int l_base, int ilev,
00582 bool a_homogeneousBC)
00583 {
00584 CH_TIME("AMRMultiGrid<T>::computeAMRResidualLevel");
00585 if (l_max != l_base)
00586 {
00587 if (ilev == l_max)
00588 {
00589 m_op[l_max]->AMRResidualNF(*(a_resid[l_max]), *(a_phi[l_max]),
00590 *(a_phi[l_max-1]), *(a_rhs[l_max]),
00591 a_homogeneousBC);
00592 }
00593 else if (ilev == l_base)
00594 {
00595 if (l_base == 0)
00596 {
00597 m_op[l_base]->AMRResidualNC(*(a_resid[l_base]), *(a_phi[l_base+1]),
00598 *(a_phi[l_base]), *(a_rhs[l_base]),
00599 a_homogeneousBC, m_op[l_base+1]);
00600 }
00601 else
00602 {
00603 m_op[l_base]->AMRResidual(*a_resid[l_base], *a_phi[l_base+1], *a_phi[l_base],
00604 *a_phi[l_base-1], *a_rhs[l_base],
00605 a_homogeneousBC, m_op[l_base+1]);
00606 }
00607 }
00608 else
00609 {
00610 m_op[ilev]->AMRResidual(*a_resid[ilev], *a_phi[ilev+1], *a_phi[ilev],
00611 *a_phi[ilev-1], *a_rhs[ilev],
00612 a_homogeneousBC, m_op[ilev+1]);
00613 }
00614 }
00615 else
00616 {
00617 CH_assert(ilev == l_base);
00618 if (l_base == 0)
00619 {
00620 m_op[l_max]->residual(*a_resid[l_max], *a_phi[l_max], *a_rhs[l_max],a_homogeneousBC);
00621 }
00622 else
00623 {
00624 m_op[l_max]->AMRResidualNF(*(a_resid[l_max]), *(a_phi[l_max]),
00625 *(a_phi[l_max-1]), *(a_rhs[l_max]),
00626 a_homogeneousBC);
00627 }
00628 }
00629
00630 }
00631
00632 template<class T>
00633 void AMRMultiGrid<T>::solve(Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00634 int l_max, int l_base, bool a_zeroPhi)
00635 {
00636 CH_TIME("AMRMultiGrid::solve");
00637 init(a_phi, a_rhs, l_max, l_base);
00638 solveNoInit(a_phi, a_rhs, l_max, l_base, a_zeroPhi);
00639
00640 revert(a_phi, a_rhs, l_max, l_base);
00641 }
00642
00643 template<class T>
00644 void AMRMultiGrid<T>::solveNoInit(Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00645 int l_max, int l_base, bool a_zeroPhi)
00646 {
00647 CH_TIMERS("AMRMultiGrid::solveNoInit");
00648 CH_TIMER("AMRMultiGrid::AMRVcycle", vtimer);
00649 setBottomSolver(l_max, l_base);
00650
00651 CH_assert(l_base <= l_max);
00652 CH_assert(a_rhs.size() == a_phi.size());
00653
00654
00655
00656 Vector<T*> uberCorrection(a_rhs.size());
00657 Vector<T*> uberResidual(a_rhs.size());
00658
00659 int lowlim = l_base;
00660 if (l_base > 0)
00661 lowlim--;
00662
00663 for (int ilev = lowlim; ilev <= l_max; ilev++)
00664 {
00665 uberCorrection[ilev] = new T();
00666 uberResidual[ilev] = new T();
00667 m_op[ilev]->create(*uberCorrection[ilev], *a_phi[ilev]);
00668 if (ilev >= l_base)
00669 {
00670 m_op[ilev]->create(*uberResidual[ilev], *a_rhs[ilev]);
00671 }
00672 m_op[ilev]->setToZero(*(uberCorrection[ilev]));
00673
00674 }
00675
00676 if(a_zeroPhi)
00677 for(int ilev = l_base; ilev <=l_max; ++ilev)
00678 {
00679 m_op[ilev]->setToZero(*(a_phi[ilev]));
00680 }
00681
00682
00683 Real initial_rnorm = 0;
00684 {
00685 CH_TIME("Initial AMR Residual");
00686 initial_rnorm=computeAMRResidual(uberResidual, a_phi, a_rhs, l_max, l_base);
00687 }
00688
00689 if (m_convergenceMetric != 0.)
00690 {
00691 initial_rnorm = m_convergenceMetric;
00692 }
00693
00694 Real rnorm = initial_rnorm;
00695 Real norm_last = 2*initial_rnorm;
00696
00698 m_bottomSolver->setConvergenceMetrics(initial_rnorm, m_eps);
00699
00700 int iter=0;
00701 if (m_verbosity >= 3)
00702 {
00703 pout() << " AMRMultiGrid:: iteration = " << iter << ", error norm = " << rnorm << std::endl;
00704 }
00705 bool goNorm = rnorm > m_normThresh;
00706 bool goRedu = rnorm > m_eps*initial_rnorm;
00707 bool goIter = iter < m_iterMax;
00708 bool goHang = iter < m_imin || rnorm <(1-m_hang)*norm_last;
00709 while (goIter && goRedu && goHang && goNorm)
00710 {
00711 norm_last = rnorm;
00712
00713
00714 CH_START(vtimer);
00715 AMRVCycle(uberCorrection, uberResidual, l_max, l_max, l_base);
00716 CH_STOP(vtimer);
00717
00718
00719 for (int ilev = l_base; ilev <= l_max; ilev++)
00720 {
00721 m_op[ilev]->incr(*(a_phi[ilev]), *(uberCorrection[ilev]), 1.0);
00722 m_op[ilev]->setToZero(*(uberCorrection[ilev]));
00723 }
00724
00725
00726 rnorm = computeAMRResidual(uberResidual, a_phi, a_rhs, l_max, l_base);
00727 iter++;
00728 if (m_verbosity >= 3)
00729 {
00730 pout() << " AMRMultiGrid:: iteration = " << iter << ", error norm = " << rnorm
00731 << ", rate = " << norm_last/rnorm << std::endl;
00732 }
00733
00734 goNorm = rnorm > m_normThresh;
00735 goRedu = rnorm > m_eps*initial_rnorm;
00736 goIter = iter < m_iterMax;
00737 goHang = iter < m_imin || rnorm <(1-m_hang)*norm_last;
00738 }
00739 m_exitStatus = int(!goRedu) + int(!goIter)*2 + int(!goHang)*4 + int(!goNorm)*8;
00740 if (m_verbosity >= 3)
00741 {
00742 pout() << " AMRMultiGrid:: iteration = " << iter << ", error norm = " << rnorm << std::endl;
00743 }
00744 if (m_verbosity > 1)
00745 {
00746 if (!goIter && goRedu && goNorm)
00747 {
00748 pout() << " AMRMultiGrid:: WARNING: Exit because max iteration count exceeded" << std::endl;
00749 }
00750 if (!goHang && goRedu && goNorm)
00751 {
00752 pout() << " AMRMultiGrid:: WARNING: Exit because of solver hang" << std::endl;
00753 }
00754 if (m_verbosity > 4)
00755 {
00756 pout() << " AMRMultiGrid:: exitStatus = " << m_exitStatus << std::endl;
00757 }
00758 }
00759 for (int i = lowlim; i <= l_max; i++)
00760 {
00761 m_op[i]->clear(*uberCorrection[i]);
00762 m_op[i]->clear(*uberResidual[i]);
00763 delete uberCorrection[i];
00764 delete uberResidual[i];
00765 }
00766 }
00767
00768
00769 template<class T>
00770 void AMRMultiGrid<T>::relaxOnlyHomogeneous(Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00771 int l_max, int l_base)
00772 {
00773 CH_TIME("AMRMultiGrid::relaxOnly");
00774 CH_assert(l_max == l_base);
00775 CH_assert(l_max == 0);
00776 init(a_phi, a_rhs, l_max, l_base);
00777
00778 CH_assert(a_rhs.size() == a_phi.size());
00779
00780 Vector<T*> uberResidual(a_rhs.size());
00781
00782 for (int ilev = 0; ilev < m_op.size(); ilev++)
00783 {
00784 uberResidual[ilev] = new T();
00785 m_op[ilev]->create(*uberResidual[ilev], *a_rhs[ilev]);
00786 }
00787
00788
00789 m_op[0]->residual(*uberResidual[0], *a_phi[0], *a_rhs[0], true);
00790 Real initial_rnorm = m_op[0]->norm(*uberResidual[0], 0);
00791 Real rnorm = initial_rnorm;
00792 Real norm_last = 2*initial_rnorm;
00793
00794
00795 int iter=0;
00796 if (m_verbosity >= 3)
00797 {
00798 pout() << " AMRMultiGrid::relaxOnly iteration = " << iter << ", error norm = " << rnorm << std::endl;
00799 }
00800 bool goNorm = rnorm > m_normThresh;
00801 bool goRedu = rnorm > m_eps*initial_rnorm;
00802 bool goIter = iter < m_iterMax;
00803 bool goHang = iter < m_imin || rnorm <(1-m_hang)*norm_last;
00804 while (goIter && goRedu && goHang && goNorm)
00805 {
00806 norm_last = rnorm;
00807 m_op[0]->relax(*a_phi[0], *a_rhs[0], 1);
00808
00809 iter++;
00810
00811 m_op[0]->residual(*uberResidual[0], *a_phi[0], *a_rhs[0], true);
00812 rnorm = m_op[0]->norm(*uberResidual[0], 2);
00813 if (m_verbosity >= 4)
00814 {
00815 pout() << " AMRMultiGrid::relaxOnly iteration = " << iter << ", error norm = " << rnorm
00816 << ", rate = " << norm_last/rnorm << std::endl;
00817 }
00818 goNorm = rnorm > m_normThresh;
00819 goRedu = rnorm > m_eps*initial_rnorm;
00820 goIter = iter < m_iterMax;
00821 goHang = iter < m_imin || rnorm <(1-m_hang)*norm_last;
00822 }
00823 m_exitStatus = 0;
00824 for (int i = 0; i < m_op.size(); i++)
00825 {
00826 m_op[i]->clear(*uberResidual[i]);
00827 delete uberResidual[i];
00828 }
00829 }
00830
00831 template <class T>
00832 void AMRMultiGrid<T>::clear()
00833 {
00834 for (int i = 0; i < m_op.size(); i++)
00835 {
00836 m_op[i]->clear(*m_correction[i]);
00837 m_op[i]->clear(*m_residual[i]);
00838 m_op[i]->clear(*m_resC[i]);
00839
00840 delete m_correction[i];
00841 delete m_residual[i];
00842 delete m_resC[i];
00843 delete m_op[i];
00844 delete m_mg[i];
00845
00846 m_correction[i] = NULL;
00847 m_residual[i] = NULL;
00848 m_resC[i] = NULL;
00849 m_op[i] = NULL;
00850 m_mg[i] = NULL;
00851 }
00852 }
00853
00854 template <class T>
00855 void AMRMultiGrid<T>::init(const Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00856 int l_max, int l_base)
00857 {
00858 CH_TIME("AMRMultiGrid::init");
00859
00860
00861 for (int i = l_base; i <= l_max; i++)
00862 {
00863 AMRLevelOp<T>& op = *(m_op[i]);
00864
00865 op.create(*m_correction[i], *a_phi[i]);
00866 op.create(*m_residual[i], *a_rhs[i]);
00867 int r = op.refToCoarser();
00868 if(i!= l_base)
00869 {
00870 int intermediateDepth = 0;
00871
00872 while(r>2)
00873 {
00874 r/=2;
00875 intermediateDepth++;
00876 }
00877 m_mg[i]->m_depth = intermediateDepth;
00878 }
00879 m_mg[i]->init(*a_phi[i], *a_rhs[i]);
00880
00881 r = op.refToCoarser();
00882 op.createCoarsened(*m_resC[i], *a_rhs[i], r);
00883 if (i != l_base)
00884 {
00885 op.buildCopier(m_resCopier[i], *a_rhs[i-1], *m_resC[i]);
00886 m_reverseCopier[i] = m_resCopier[i];
00887 m_reverseCopier[i].reverse();
00888 }
00889 }
00890 }
00891 template <class T>
00892 void AMRMultiGrid<T>::revert(const Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00893 int l_max, int l_base)
00894 {
00895 CH_TIME("AMRMultiGrid::init");
00896 for (int i = l_base; i <= l_max; i++)
00897 {
00898 if(i!= l_base)
00899 {
00900 m_mg[i]->m_depth = m_mg[i]->m_defaultDepth;
00901 }
00902 }
00903 }
00904
00905 template <class T>
00906 void AMRMultiGrid<T>::setBottomSolver(int l_max, int l_base)
00907 {
00908
00909 for (int ilev = l_base; ilev <= l_max; ilev++)
00910 {
00911 if(!m_solverParamsSet)
00912 {
00913 m_mg[ilev]->m_pre=1;
00914 m_mg[ilev]->m_post=1;
00915 m_mg[ilev]->m_bottom = m_bottom;
00916 }
00917 m_mg[ilev]->m_bottomSolver = &m_nosolve;
00918 }
00919
00920 if(!m_solverParamsSet)
00921 {
00922 m_mg[l_base]->m_pre = m_pre;
00923 m_mg[l_base]->m_post = m_post;
00924 m_mg[l_base]->m_bottom = 0;
00925 }
00926 m_mg[l_base]->setBottomSolver(m_bottomSolver);
00927 }
00928
00929 template <class T>
00930 void AMRMultiGrid<T>::define(const ProblemDomain& a_coarseDomain,
00931 AMRLevelOpFactory<T>& a_factory,
00932 LinearSolver<T>* a_bottomSolver,
00933 int a_maxAMRLevels)
00934 {
00935 CH_TIME("AMRMultiGrid::define");
00936 this->clear();
00937 m_op.resize( a_maxAMRLevels, NULL);
00938 m_mg.resize( a_maxAMRLevels, NULL);
00939
00940
00941 m_correction.resize( a_maxAMRLevels, NULL);
00942 m_residual. resize( a_maxAMRLevels, NULL);
00943 m_resC. resize( a_maxAMRLevels, NULL);
00944 m_resCopier. resize( a_maxAMRLevels);
00945 m_reverseCopier.resize( a_maxAMRLevels);
00946 m_bottomSolver = a_bottomSolver;
00947
00948 ProblemDomain current = a_coarseDomain;
00949 for (int i = 0; i < a_maxAMRLevels; i++)
00950 {
00951
00952 m_correction[i] = new T();
00953 m_residual[i] = new T();
00954 m_resC[i] = new T();
00955 m_mg[i]= new MultiGrid<T>();
00956 m_op[i] = a_factory.AMRnewOp(current);
00957 m_mg[i]->define(a_factory, &m_nosolve, current, m_maxDepth);
00958
00959
00960
00961 if (i < a_maxAMRLevels-1)
00962 {
00963 current.refine(a_factory.refToFiner(current));
00964 }
00965 }
00966 }
00967
00968 template<class T>
00969 void AMRMultiGrid<T>::AMRVCycle(Vector<T*>& a_uberCorrection,
00970 Vector<T*>& a_uberResidual,
00971 int ilev, int l_max, int l_base)
00972 {
00973 if (ilev == l_max)
00974 {
00975 for (int level = l_base; level <= l_max; level++)
00976 {
00977 m_op[level]->assignLocal(*m_residual[level], *a_uberResidual[level]);
00978 m_op[level]->setToZero(*m_correction[level]);
00979 }
00980 }
00981
00982 if (l_max == l_base)
00983 {
00984 CH_assert(ilev == l_base);
00985 m_mg[l_base]->oneCycle(*(a_uberCorrection[ilev]), *(a_uberResidual[ilev]));
00986 }
00987 else if (ilev == l_base)
00988 {
00989 m_mg[l_base]->oneCycle(*(m_correction[ilev]), *(m_residual[ilev]));
00990
00991 m_op[ilev]->incr(*(a_uberCorrection[ilev]), *(m_correction[ilev]), 1.0);
00992 }
00993 else
00994 {
00995
00996
00997
00998
00999
01000
01001 this->relax(*(m_correction[ilev]), *(m_residual[ilev]), ilev, m_pre);
01002 m_op[ilev]->incr(*(a_uberCorrection[ilev]), *(m_correction[ilev]), 1.0);
01003
01004
01005 m_op[ilev-1]->setToZero(*(m_correction[ilev-1]));
01006
01007
01008
01009
01010
01011 computeAMRResidualLevel(m_residual,
01012 a_uberCorrection,
01013 a_uberResidual,
01014 l_max, l_base, ilev-1,
01015 true);
01016
01017
01018 m_op[ilev]->AMRRestrictS(*(m_resC[ilev]),
01019 *(m_residual[ilev]),
01020 *(m_correction[ilev]),
01021 *(m_correction[ilev-1]),
01022 *(a_uberCorrection[ilev]));
01023
01024
01025
01026
01027 m_op[ilev-1]->assignCopier(*m_residual[ilev-1], *(m_resC[ilev]), m_resCopier[ilev]);
01028
01029
01030
01031 for (int img = 0; img < m_numMG; img++)
01032 {
01033 AMRVCycle(a_uberCorrection, a_uberResidual, ilev-1, l_max, l_base);
01034 }
01035
01036
01037
01038
01039 m_op[ilev]->AMRProlongS(*(m_correction[ilev]), *(m_correction[ilev-1]),
01040 *m_resC[ilev], m_reverseCopier[ilev]);
01041
01042 m_op[ilev]->AMRUpdateResidual(*(m_residual[ilev]), *(m_correction[ilev]), *(m_correction[ilev-1]));
01043
01044
01045
01046 T& dCorr = *(a_uberCorrection[ilev]);
01047 m_op[ilev]->setToZero(dCorr);
01048 this->relax(dCorr, *(m_residual[ilev]), ilev, m_post);
01049
01050
01051 m_op[ilev]->incr(*(m_correction[ilev]), dCorr, 1.0);
01052
01053
01054 m_op[ilev]->assignLocal(*(a_uberCorrection[ilev]), *(m_correction[ilev]));
01055
01056 }
01057 }
01058
01059 #include "NamespaceFooter.H"
01060 #endif