00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _GENAMRSOLVERIMPLEM_H_
00029 #define _GENAMRSOLVERIMPLEM_H_
00030
00031 #include "LayoutIterator.H"
00032
00033
00034
00035 template <class T>
00036 GenAMRSolver<T>::GenAMRSolver():m_amrmgLevel()
00037 {
00038 setDefaultValues();
00039 }
00040
00041
00042
00043 template <class T>
00044 GenAMRSolver<T>::GenAMRSolver(const Vector<DisjointBoxLayout>& a_gridsLevel,
00045 const Vector<Box>& a_domainLevel,
00046 const Vector<Real>& a_dxLevel,
00047 const Vector<int>& a_refRatio,
00048 int a_numLevels,
00049 int a_lBase,
00050 const GenAMRLevelMGOp<T>* const a_opin,
00051 int a_ncomp)
00052 :m_amrmgLevel()
00053 {
00054 setDefaultValues();
00055
00056 Vector<ProblemDomain> physdomains(a_domainLevel.size());
00057
00058 for (int lev = 0; lev < physdomains.size(); lev++)
00059 {
00060 physdomains[lev] = ProblemDomain(a_domainLevel[lev]);
00061 }
00062
00063 define(a_gridsLevel, physdomains, a_dxLevel,
00064 a_refRatio, a_numLevels, a_lBase, a_opin, a_ncomp);
00065 }
00066
00067
00068
00069 template <class T>
00070 GenAMRSolver<T>::GenAMRSolver(const Vector<DisjointBoxLayout>& a_gridsLevel,
00071 const Vector<ProblemDomain>& a_domainLevel,
00072 const Vector<Real>& a_dxLevel,
00073 const Vector<int>& a_refRatio,
00074 int a_numLevels,
00075 int a_lBase,
00076 const GenAMRLevelMGOp<T>* const a_opin,
00077 int a_ncomp)
00078 :m_amrmgLevel()
00079 {
00080 setDefaultValues();
00081
00082 define(a_gridsLevel, a_domainLevel, a_dxLevel,
00083 a_refRatio, a_numLevels, a_lBase, a_opin, a_ncomp);
00084 }
00085
00086
00087
00088 template <class T>
00089 GenAMRSolver<T>::~GenAMRSolver()
00090 {
00091 clear();
00092 }
00093
00094
00096
00097 template <class T>
00098 bool GenAMRSolver<T>::isDefined() const
00099 {
00100 return m_isDefined;
00101 }
00102
00103
00104
00105 template <class T>
00106 void GenAMRSolver<T>::define(const Vector<DisjointBoxLayout>& a_gridsLevel,
00107 const Vector<Box>& a_domainLevel,
00108 const Vector<Real>& a_dxLevel,
00109 const Vector<int>& a_refRatio,
00110 int a_numLevels,
00111 int a_lBase,
00112 const GenAMRLevelMGOp<T>* const a_opin,
00113 int a_ncomp)
00114 {
00115 setDefaultValues();
00116
00117 Vector<ProblemDomain> physdomains(a_domainLevel.size());
00118
00119 for (int lev = 0; lev < physdomains.size(); lev++)
00120 {
00121 physdomains[lev] = ProblemDomain(a_domainLevel[lev]);
00122 }
00123
00124 define(a_gridsLevel, physdomains, a_dxLevel, a_refRatio, a_numLevels,
00125 a_lBase, a_opin, a_ncomp);
00126 }
00127
00128
00129
00130 template <class T>
00131 void GenAMRSolver<T>::define(const Vector<DisjointBoxLayout>& a_gridsLevel,
00132 const Vector<ProblemDomain>& a_domainLevel,
00133 const Vector<Real>& a_dxLevel,
00134 const Vector<int>& a_refRatio,
00135 int a_numLevels,
00136 int a_lBase,
00137 const GenAMRLevelMGOp<T>* const a_opin,
00138 int a_ncomp)
00139 {
00140 clear();
00141
00142 m_isDefined = true;
00143
00144 m_gridsLevel = a_gridsLevel;
00145 m_domainLevel = a_domainLevel;
00146 m_dxLevel = a_dxLevel;
00147 m_refRatio = a_refRatio;
00148
00149 m_numLevels = a_numLevels;
00150 m_finestLevel = a_numLevels - 1;
00151
00152 m_lBase = a_lBase;
00153 m_ncomp = a_ncomp;
00154
00155
00156 m_amrmgLevel.resize(m_numLevels, NULL);
00157
00158
00159
00160 int startLev = a_lBase;
00161
00162
00163 for (int ilev = startLev; ilev < m_numLevels; ilev++)
00164 {
00165 m_amrmgLevel[ilev] = new GenAMRLevelMG<T>(this, ilev, a_opin, m_ncomp);
00166 }
00167
00168 assert(m_lBase >= 0);
00169
00170
00171 const DisjointBoxLayout& levsolvGrids = m_gridsLevel[m_lBase];
00172 const ProblemDomain& levsolvDom = m_domainLevel[m_lBase];
00173 const Real& levsolvDx = m_dxLevel[m_lBase];
00174 const DisjointBoxLayout* levsolvBase = NULL;
00175
00176
00177 int levsolvRef = -1;
00178
00179 if (m_lBase > 0)
00180 {
00181 levsolvBase = &m_gridsLevel[m_lBase-1];
00182 levsolvRef = m_refRatio[m_lBase-1];
00183 }
00184
00185 m_levelSolver.define(levsolvGrids, levsolvBase,
00186 levsolvDom, levsolvDx,
00187 levsolvRef, a_opin, m_ncomp);
00188
00189 m_levelSolver.setMaxIter(m_numVCyclesBottom);
00190 }
00191
00196 template <class T>
00197 void GenAMRSolver<T>::setNumSmoothUp(int a_numSmoothUp)
00198 {
00199 assert(a_numSmoothUp >= 0);
00200
00201 m_numSmoothUp = a_numSmoothUp;
00202
00203 for (int ilev = 0; ilev < m_numLevels; ilev++)
00204 {
00205 m_amrmgLevel[ilev]->setnumSmoothUp(m_numSmoothUp);
00206 }
00207 }
00208
00213 template <class T>
00214 void GenAMRSolver<T>::setNumSmoothDown(int a_numSmoothDown)
00215 {
00216 assert(a_numSmoothDown >= 0);
00217
00218 m_numSmoothDown = a_numSmoothDown;
00219
00220 for (int ilev = 0; ilev < m_numLevels; ilev++)
00221 {
00222 m_amrmgLevel[ilev]->setnumSmoothDown(m_numSmoothDown);
00223 }
00224 }
00225
00229 template <class T>
00230 void GenAMRSolver<T>::setTolerance(Real a_tolerance)
00231 {
00232 assert(a_tolerance >= 0);
00233
00234 m_tolerance = a_tolerance;
00235 m_errorTolerance = a_tolerance;
00236 }
00237
00242 template <class T>
00243 void GenAMRSolver<T>::setOperatorTolerance(Real a_tolerance)
00244 {
00245 assert(a_tolerance >= 0);
00246
00247 m_operatorTolerance = a_tolerance;
00248 }
00249
00253 template <class T>
00254 void GenAMRSolver<T>::setMaxIter(int a_maxIter)
00255 {
00256 assert(a_maxIter >= 0);
00257
00258 m_maxIter = a_maxIter;
00259 }
00260
00264 template <class T>
00265 void GenAMRSolver<T>::setMinIter(int a_minIter)
00266 {
00267 assert(a_minIter >= 0);
00268
00269 m_minIter = a_minIter;
00270 }
00271
00272 template <class T>
00273 void GenAMRSolver<T>::setNumVCyclesBottom(int a_numVCyclesBottom)
00274 {
00275 assert(a_numVCyclesBottom >= 0);
00276
00277 m_numVCyclesBottom = a_numVCyclesBottom;
00278 m_levelSolver.setMaxIter(m_numVCyclesBottom);
00279 }
00280
00282 template <class T>
00283 void GenAMRSolver<T>::solveAMR(Vector<T *>& a_phiLevel,
00284 const Vector<T *>& a_rhsLevel)
00285 {
00286 assert(isDefined());
00287 assert(a_phiLevel.size() > m_finestLevel);
00288 assert(a_rhsLevel.size() > m_finestLevel);
00289
00290 int ncomp = a_phiLevel[m_lBase]->nComp();
00291
00292 if (ncomp > m_ncomp)
00293 {
00294 MayDay::Warning("GenAMRSolver::solveAMR -- phi.nComp > solver.ncomp");
00295 ncomp = m_ncomp;
00296 }
00297
00298 Vector<T *> residVect(m_finestLevel+1,NULL);
00299 Vector<T *> corrVect(m_finestLevel+1,NULL);
00300
00301
00302
00303 for (int ilev = m_lBase; ilev <= m_finestLevel; ilev++)
00304 {
00305 const DisjointBoxLayout& levelGrids = a_phiLevel[ilev]->getBoxes();
00306
00307 residVect[ilev] = new T(levelGrids, ncomp);
00308 corrVect[ilev] = new T(levelGrids, ncomp, IntVect::Unit);
00309
00310 T& phiLev = *a_phiLevel[ilev];
00311 T& corrLev = *corrVect[ilev];
00312
00313 GenAMRLevelMGOp<T>& levelopCur = *(m_amrmgLevel[ilev]->m_levelopPtr);
00314
00315 levelopCur.setToZero(phiLev);
00316 levelopCur.setToZero(corrLev);
00317 }
00318
00319
00320
00321 if (m_lBase > 0)
00322 {
00323 const DisjointBoxLayout& crseGrids = a_phiLevel[m_lBase-1]->getBoxes();
00324
00325 corrVect[m_lBase-1] = new T(crseGrids, ncomp,
00326 IntVect::Unit);
00327
00328
00329 T& crseCorr = *corrVect[m_lBase-1];
00330
00331 GenAMRLevelMGOp<T>& crseLevelop = *(m_amrmgLevel[m_lBase-1]->m_levelopPtr);
00332 crseLevelop.setToZero(crseCorr);
00333 }
00334
00335 Vector<Real> initRes = computeResidualNorm(residVect, a_phiLevel,
00336 a_rhsLevel, 0);
00337
00338 Vector<Real> currentRes = initRes;
00339 Vector<Real> oldRes = initRes;
00340
00341 if (m_verbose)
00342 {
00343 pout() << "GenAMRSolver, lBase = " << m_lBase << endl;
00344 for (int comp = 0; comp < ncomp; comp++)
00345 {
00346 pout() << "initial max(residual[" << comp << "]) = "
00347 << initRes[comp] << endl;
00348 }
00349 }
00350
00351
00352 bool done = true;
00353
00354 for (int comp = 0; comp < ncomp; comp++)
00355 {
00356 if (initRes[comp] != 0)
00357 {
00358 done = false;
00359 }
00360 }
00361
00362 if (done)
00363 {
00364 if (m_verbose)
00365 {
00366 pout() << "GenAMRSolver::solveAMR--initial residual == 0\n returning... \n";
00367 }
00368 return;
00369 }
00370
00371 int iter = 0;
00372
00373 while (!done)
00374 {
00375 AMRVCycleMG(corrVect, residVect);
00376
00377
00378
00379
00380
00381 for (int ilev = m_lBase; ilev <= m_finestLevel; ilev++)
00382 {
00383 T& levelCorr = *corrVect[ilev];
00384 T& levelPhi = *a_phiLevel[ilev];
00385
00386 GenAMRLevelMGOp<T>& levelopCur = *(m_amrmgLevel[ilev]->m_levelopPtr);
00387
00388 levelopCur.sum(levelPhi,levelCorr);
00389 levelopCur.setToZero(levelCorr);
00390 }
00391
00392 oldRes = currentRes;
00393 currentRes = computeResidualNorm(residVect, a_phiLevel,
00394 a_rhsLevel, 0);
00395
00396 iter++;
00397
00398 done = true;
00399
00400 for (int comp = 0; comp < ncomp; comp++)
00401 {
00402
00403
00404
00405
00406 done = done &&
00407 ((iter > m_maxIter)
00408 || ((iter > m_minIter) && (currentRes[comp] >
00409 oldRes[comp]*(1.0-m_operatorTolerance)))
00410 || (currentRes[comp] <= m_tolerance*initRes[comp]));
00411
00412 if (m_verbose)
00413 {
00414 pout() << "iteration # " << iter
00415 << ": Max(res[" << comp << "]) = "
00416 << currentRes[comp] << endl;
00417 }
00418 }
00419 }
00420
00421 for (int comp = 0; comp < ncomp; comp++)
00422 {
00423 if (currentRes[comp] <= m_tolerance*initRes[comp])
00424 {
00425 if (m_verbose)
00426 {
00427 pout() << "GenAMRSolver: " << iter << " iterations, final max(res["
00428 << comp << "]) = "
00429 << currentRes[comp] << endl;
00430 }
00431 }
00432 else if (iter > m_maxIter)
00433 {
00434 if (m_verbose)
00435 {
00436 pout() << "GenAMRSolver: reached maximum number of "
00437 << iter << " iterations, final max(res)[" << comp
00438 << "] = " << currentRes[comp] << endl;
00439 }
00440 }
00441 else if (currentRes[comp] > oldRes[comp]*(1.0-m_operatorTolerance))
00442 {
00443 if (m_verbose)
00444 {
00445 pout() << "GenAMRSolver: reached solver hang point; " << iter
00446 << " iterations, final max(res[" << comp
00447 << "]) = " << currentRes[comp] << endl;
00448 }
00449 }
00450 else
00451 {
00452 if (m_verbose)
00453 {
00454 pout() << "GenAMRSolver NOT CONVERGED! - final max(res) = "
00455 << currentRes[comp] << " after " << iter << " iterations" << endl;
00456 }
00457 }
00458 }
00459
00460
00461 for (int ilev = 0; ilev <= m_finestLevel; ilev++)
00462 {
00463 if (residVect[ilev] != NULL)
00464 {
00465 delete residVect[ilev];
00466 residVect[ilev] = NULL;
00467 }
00468
00469 if (corrVect[ilev] != NULL)
00470 {
00471 delete corrVect[ilev];
00472 corrVect[ilev] = NULL;
00473 }
00474 }
00475 }
00476
00481 template <class T>
00482 void GenAMRSolver<T>::AMRVCycleMG(Vector<T *>& a_corrLevel,
00483 const Vector<T *>& a_residLevel)
00484 {
00485 assert(isDefined());
00486 assert(a_corrLevel.size() > m_finestLevel);
00487 assert(a_residLevel.size() > m_finestLevel);
00488
00489
00490
00491 Interval compInterval = a_residLevel[m_lBase]->interval();
00492 for (int ilev = m_lBase; ilev <= m_finestLevel; ilev++)
00493 {
00494 T& levelResid = m_amrmgLevel[ilev]->m_resid;
00495
00496 a_residLevel[ilev]->copyTo(compInterval, levelResid, compInterval);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 for (int ilev = m_finestLevel; ilev > m_lBase; ilev--)
00514 {
00515 m_amrmgLevel[ilev]->downSweep(a_corrLevel,a_residLevel);
00516 }
00517
00518
00519 T & bottomCorr = m_amrmgLevel[m_lBase]->m_corr;
00520 const T & bottomRes = m_amrmgLevel[m_lBase]->m_resid;
00521
00522
00523 if (m_finestLevel == m_lBase)
00524 {
00525
00526
00527 m_levelSolver.levelSolveH(*a_corrLevel[m_lBase],
00528 *a_residLevel[m_lBase]);
00529 }
00530 else
00531 {
00532 m_levelSolver.levelSolveH(bottomCorr, bottomRes);
00533
00534
00535 T & bottomPhi = *a_corrLevel[m_lBase];
00536 GenAMRLevelMGOp<T>& bottomLevelop = *(m_amrmgLevel[m_lBase]->m_levelopPtr);
00537
00538 bottomLevelop.sum(bottomPhi,bottomCorr);
00539 }
00540
00541
00542 for (int ilev = m_lBase+1; ilev <= m_finestLevel; ilev++)
00543 {
00544 m_amrmgLevel[ilev]->upSweep(a_corrLevel,a_residLevel);
00545 }
00546 }
00547
00552 template <class T>
00553 Vector<Real> GenAMRSolver<T>::computeResidualNorm(Vector<T *>& a_phiLevel,
00554 const Vector<T *>& a_rhsLevel,
00555 int a_normType)
00556 {
00557 assert(isDefined());
00558 assert(a_phiLevel.size() > m_finestLevel);
00559 assert(a_rhsLevel.size() > m_finestLevel);
00560 assert((a_normType >= 0) && (a_normType <= 2));
00561
00562 int ncomp = a_phiLevel[m_lBase]->nComp();
00563
00564 if (ncomp > m_ncomp)
00565 {
00566 ncomp = m_ncomp;
00567 }
00568
00569 Vector<Real> normTot(ncomp,0);
00570 Vector<Real> normLevel(ncomp,0.0);
00571
00572 for (int ilev = m_finestLevel; ilev >= m_lBase; ilev--)
00573 {
00574 m_amrmgLevel[ilev]->setArrayViewVerbose(false);
00575 m_amrmgLevel[ilev]->computeAMRResidual(a_phiLevel, a_rhsLevel);
00576
00577 normLevel = m_amrmgLevel[ilev]->computeResidualNorm(a_normType);
00578
00579 for (int comp = 0; comp < ncomp; comp++)
00580 {
00581 if (a_normType == 0)
00582 {
00583 normTot[comp] = Max(normTot[comp], normLevel[comp]);
00584 }
00585 else
00586 {
00587 normTot[comp] += normLevel[comp];
00588 }
00589 }
00590 }
00591
00592 if (a_normType == 2)
00593 {
00594 for (int comp = 0; comp < ncomp; comp++)
00595 {
00596 normTot[comp] = sqrt(normTot[comp]);
00597 }
00598 }
00599
00600 return normTot;
00601 }
00602
00608 template <class T>
00609 Vector<Real> GenAMRSolver<T>::computeResidualNorm(Vector<T *>& a_residLevel,
00610 Vector<T *>& a_phiLevel,
00611 const Vector<T *>& a_rhsLevel,
00612 int a_normType)
00613 {
00614 assert(isDefined());
00615 assert(a_phiLevel.size() > m_finestLevel);
00616 assert(a_rhsLevel.size() > m_finestLevel);
00617 assert((a_normType >= 0) && (a_normType <= 2));
00618
00619 int ncomp = a_phiLevel[m_lBase]->nComp();
00620 if (ncomp > m_ncomp)
00621 {
00622 ncomp = m_ncomp;
00623 }
00624
00625 Vector<Real> normTot(ncomp,0);
00626
00627 Vector<Real> normLevel(ncomp,0.0);
00628
00629 for (int ilev = m_finestLevel; ilev >= m_lBase; ilev--)
00630 {
00631 T& levelResid = *a_residLevel[ilev];
00632 m_amrmgLevel[ilev]->computeAMRResidual(levelResid, a_phiLevel, a_rhsLevel);
00633
00634 normLevel = m_amrmgLevel[ilev]->computeNorm(levelResid,a_normType);
00635
00636 for (int comp = 0; comp < ncomp; comp++)
00637 {
00638 if (a_normType == 0)
00639 {
00640 normTot[comp] = Max(normTot[comp], normLevel[comp]);
00641 }
00642 else
00643 {
00644 normTot[comp] += normLevel[comp];
00645 }
00646 }
00647 }
00648
00649 if (a_normType == 2)
00650 {
00651 for (int comp = 0; comp < ncomp; comp++)
00652 {
00653 normTot[comp] = sqrt(normTot[comp]);
00654 }
00655 }
00656
00657 return normTot;
00658 }
00659
00663 template <class T>
00664 void GenAMRSolver<T>::computeAMRResidual(Vector<T *>& a_phiLevel,
00665 const Vector<T *>& a_rhsLevel,
00666 T& a_res,
00667 int a_ilev)
00668 {
00669 assert(isDefined());
00670 assert(a_ilev <= m_finestLevel);
00671 assert(a_ilev >= 0);
00672 assert(a_phiLevel.size() > m_finestLevel);
00673 assert(a_rhsLevel.size() > m_finestLevel);
00674 assert(a_rhsLevel[a_ilev]->getBoxes() == m_gridsLevel[a_ilev]);
00675 assert(a_phiLevel[a_ilev]->getBoxes() == m_gridsLevel[a_ilev]);
00676 assert(a_res.getBoxes() == m_gridsLevel[a_ilev]);
00677
00678
00679 m_amrmgLevel[a_ilev]->computeAMRResidual(a_phiLevel,a_rhsLevel);
00680 const T & amrmgRes = m_amrmgLevel[a_ilev]->m_resid;
00681
00682 assert(amrmgRes.getBoxes() == m_gridsLevel[a_ilev]);
00683
00684
00685 GenAMRLevelMGOp<T>& levelop = *(m_amrmgLevel[a_ilev]->m_levelopPtr);
00686
00687 levelop->copy(a_res,amrmgRes);
00688 }
00689
00694 template <class T>
00695 void GenAMRSolver<T>::applyAMROperator(Vector<T *>& a_phiLevel,
00696 T& a_LOfPhi,
00697 int a_ilev)
00698 {
00699 assert(isDefined());
00700 assert(a_ilev <= m_finestLevel);
00701 assert(a_ilev >= 0);
00702 assert(a_phiLevel.size() > m_finestLevel);
00703
00704 m_amrmgLevel[a_ilev]->applyAMROperator(a_phiLevel,a_LOfPhi);
00705 }
00706
00712 template <class T>
00713 void GenAMRSolver<T>::applyAMROperatorHphys(Vector<T* >& a_phiLevel,
00714 T& a_LOfPhi,
00715 int a_ilev)
00716 {
00717 assert(isDefined());
00718 assert(a_ilev <= m_finestLevel);
00719 assert(a_ilev >= 0);
00720 assert(a_phiLevel.size() > m_finestLevel);
00721
00722 m_amrmgLevel[a_ilev]->applyAMROperatorHphys(a_phiLevel,a_LOfPhi);
00723 }
00724
00728 template <class T>
00729 void GenAMRSolver<T>::setVerbose(bool a_verbose)
00730 {
00731 assert(isDefined());
00732
00733 m_verbose = a_verbose;
00734 }
00735
00736
00737
00738 template <class T>
00739 void GenAMRSolver<T>::setDefaultValues()
00740 {
00741 m_numLevels = -1;
00742 m_finestLevel = -1;
00743 m_refRatio.resize(0);
00744 m_numVCyclesBottom = 1;
00745
00746 m_tolerance = 1.0e-10;
00747 #ifdef CH_USE_FLOAT
00748 m_tolerance = 10.*sqrt(m_tolerance);
00749 #endif
00750 m_errorTolerance = m_tolerance;
00751 m_operatorTolerance = 1.0e-4;
00752
00753 m_maxIter = 42;
00754 m_minIter = 4;
00755
00756 m_numSmoothUp = 4;
00757 m_numSmoothDown = 4;
00758
00759 m_isDefined = false;
00760
00761 m_ncomp = 1;
00762
00763 m_verbose = false;
00764 }
00765
00766
00767
00768 template <class T>
00769 void GenAMRSolver<T>::clear()
00770 {
00771 for (int ilev = 0; ilev < m_amrmgLevel.size(); ilev++)
00772 {
00773 if (m_amrmgLevel[ilev] != NULL)
00774 {
00775 delete m_amrmgLevel[ilev];
00776 }
00777 }
00778 }
00779
00780 #endif