00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _MULTILEVELLINEAROPI_H_
00012 #define _MULTILEVELLINEAROPI_H_
00013
00014 #include "AMRIO.H"
00015
00016 #include "NamespaceHeader.H"
00017
00018
00019
00020 template<class T>
00021 MultilevelLinearOp<T>::MultilevelLinearOp()
00022 {
00023
00024 m_use_multigrid_preconditioner = true;
00025 m_num_mg_iterations = 1;
00026 m_num_mg_smooth = 4;
00027
00028 m_preCondSolverDepth = -1;
00029 m_precondBottomSolverPtr = NULL;
00030 }
00031
00033 template<class T>
00034 void
00035 MultilevelLinearOp<T>::define(const Vector<DisjointBoxLayout>& a_vectGrids,
00036 const Vector<int>& a_refRatios,
00037 const Vector<ProblemDomain>& a_domains,
00038 const Vector<RealVect>& a_vectDx,
00039 RefCountedPtr<AMRLevelOpFactory<LevelData<T> > >& a_opFactory,
00040 int a_lBase)
00041 {
00042 CH_TIME("MultilevelLinearOp::define");
00043
00044 int numLevels = a_vectGrids.size();
00045
00046
00047 CH_assert (a_lBase >= 0);
00048 CH_assert (a_lBase < numLevels);
00049 CH_assert ( a_domains.size() == numLevels);
00050
00051 CH_assert (a_refRatios.size() >= numLevels -1);
00052
00053
00054 m_lBase = a_lBase;
00055
00056 m_vectGrids = a_vectGrids;
00057 m_refRatios = a_refRatios;
00058 m_domains = a_domains;
00059 m_vectDx = a_vectDx;
00060 m_vectOperators.resize(numLevels);
00061
00062
00063 int coarsestLevel = Max(0, m_lBase-1);
00064 for (int level=coarsestLevel; level<numLevels; level++)
00065 {
00066 RefCountedPtr<AMRLevelOp<LevelData<T> > > op = RefCountedPtr<AMRLevelOp<LevelData<T> > >(a_opFactory->AMRnewOp(m_domains[level]));
00067 m_vectOperators[level] = op;
00068 }
00069
00070
00071 if (m_use_multigrid_preconditioner)
00072 {
00073
00074 BiCGStabSolver<LevelData<T> >* newPtr = new BiCGStabSolver<LevelData<T> >;
00075
00076 m_precondBottomSolverPtr = newPtr;
00077 int bottomSolverVerbosity = 1;
00078
00079 newPtr->m_verbosity = bottomSolverVerbosity;
00080
00081 if (m_preCondSolverDepth >= 0)
00082 {
00083 m_preCondSolver.m_maxDepth = m_preCondSolverDepth;
00084 }
00085 m_preCondSolver.define(m_domains[0],
00086 *a_opFactory,
00087 m_precondBottomSolverPtr,
00088 numLevels);
00089
00090
00091
00092 Real solverEps = 1.0e-7;
00093 int maxIterations = 1;
00094 Real hang = 1.0e-7;
00095 Real normThresh = 1.0e-30;
00096
00097 int num_mg = 1;
00098 m_preCondSolver.setSolverParameters(m_num_mg_smooth,
00099 m_num_mg_smooth,
00100 m_num_mg_smooth,
00101 num_mg,
00102 maxIterations,
00103 solverEps,
00104 hang,
00105 normThresh);
00106
00107
00108 m_preCondSolver.m_verbosity = 1;
00109
00110
00111
00112 m_isPrecondSolverInitialized = false;
00113
00114 }
00115
00116
00117 }
00118
00120 template<class T>
00121 MultilevelLinearOp<T>::~MultilevelLinearOp()
00122 {
00123 CH_TIME("MultilevelLinearOp::~MultilevelLinearOp");
00124
00125 if (m_precondBottomSolverPtr != NULL)
00126 {
00127 delete m_precondBottomSolverPtr;
00128 m_precondBottomSolverPtr = NULL;
00129 }
00130 }
00131
00133
00138 template<class T>
00139 void
00140 MultilevelLinearOp<T>::residual(Vector<LevelData<T>* >& a_lhs,
00141 const Vector<LevelData<T>* >& a_phi,
00142 const Vector<LevelData<T>* >& a_rhs,
00143 bool a_homogeneous )
00144 {
00145 CH_TIME("MultilevelLinearOp::residual");
00146
00147
00148 LevelData<T> dummyT;
00149
00150 int numLevels = a_lhs.size();
00151 CH_assert (a_phi.size() == numLevels);
00152 CH_assert (a_rhs.size() == numLevels);
00153 CH_assert (m_vectOperators.size() >= numLevels);
00154
00155 int maxLevel = numLevels -1;
00156 for (int level = m_lBase; level < numLevels; level++)
00157 {
00158 const LevelData<T>& thisPhi = *(a_phi[level]);
00159 LevelData<T>& thisResid = *(a_lhs[level]);
00160 const LevelData<T>& thisRHS = *(a_rhs[level]);
00161
00162 if (level >0)
00163 {
00164 const LevelData<T>& phiCrse = *a_phi[level-1];
00165
00166 if (level < maxLevel)
00167 {
00168 const LevelData<T>& phiFine = *a_phi[level+1];
00169 m_vectOperators[level]->AMRResidual(thisResid,
00170 phiFine,
00171 thisPhi,
00172 phiCrse,
00173 thisRHS,
00174 a_homogeneous,
00175 (m_vectOperators[level+1].operator->()));
00176 }
00177 else
00178 {
00179
00180 m_vectOperators[level]->AMRResidualNF(thisResid,
00181 thisPhi,
00182 phiCrse,
00183 thisRHS,
00184 a_homogeneous);
00185 }
00186
00187 }
00188 else
00189 {
00190
00191 if (level < maxLevel)
00192 {
00193 const LevelData<T>& phiFine = *a_phi[level+1];
00194 m_vectOperators[level]->AMRResidualNC(thisResid,
00195 phiFine,
00196 thisPhi,
00197 thisRHS,
00198 a_homogeneous,
00199 (m_vectOperators[level+1].operator->()));
00200 }
00201 else
00202 {
00203
00204 m_vectOperators[level]->residual(thisResid,
00205 thisPhi,
00206 thisRHS,
00207 a_homogeneous);
00208 }
00209 }
00210 }
00211 }
00212
00213
00214
00216
00220 template<class T>
00221 void
00222 MultilevelLinearOp<T>::preCond(Vector<LevelData<T>* >& a_cor,
00223 const Vector<LevelData<T>* >& a_residual)
00224
00225 {
00226 CH_TIME("MultilevelLinearOp::preCond");
00227
00228
00229 int numLevels = a_cor.size();
00230 CH_assert (a_residual.size() == numLevels);
00231 CH_assert (m_vectOperators.size() <= numLevels);
00232
00233
00234 if (m_use_multigrid_preconditioner)
00235 {
00236 CH_TIME("MultilevelLinearOp::preCond::Multigrid");
00237
00238 Vector<LevelData<T>* > localCorr;
00239 Vector<LevelData<T>* > localResid;
00240 create(localCorr, a_cor);
00241 create(localResid, a_residual);
00242
00243
00244
00245 Vector<LevelData<T>* > tempCorr(numLevels, NULL);
00246 Vector<LevelData<T>* > tempResid(numLevels, NULL);
00247
00248 {
00249 CH_TIME("MultilevelLinearOp::preCond::Multigrid::NewStorage");
00250
00251
00252 for (int lev=0; lev<numLevels; lev++)
00253 {
00254 tempCorr[lev] = localCorr[lev];
00255 tempResid[lev] = const_cast<LevelData<T>*>(localResid[lev]);
00256 }
00257 }
00258
00259 int finestLevel = numLevels -1;
00260 {
00261 CH_TIME("MultilevelLinearOp::preCond::Multigrid::Initialize");
00262
00263 if (!m_isPrecondSolverInitialized)
00264 {
00265
00266 m_preCondSolver.init(tempCorr, tempResid, finestLevel,
00267 m_lBase);
00268
00269 m_preCondSolver.setBottomSolver(finestLevel, m_lBase);
00270 m_isPrecondSolverInitialized = true;
00271 }
00272 }
00273
00274 for (int iter = 0; iter<m_num_mg_iterations; iter++)
00275 {
00276 CH_TIME("MultilevelLinearOp::preCond::Multigrid::Iterate");
00277
00278
00279
00280
00281
00282
00283
00284
00285 bool homogeneous = true;
00286 residual(localResid, a_cor, a_residual, homogeneous);
00287 setToZero(localCorr);
00288
00289 m_preCondSolver.AMRVCycle(tempCorr, tempResid,
00290 finestLevel, finestLevel,
00291 m_lBase);
00292
00293
00294 incr(a_cor, localCorr, 1.0);
00295 }
00296
00297 {
00298 CH_TIME("MultilevelLinearOp::preCond::Multigrid::Clear");
00299
00300 clear(localCorr);
00301 clear(localResid);
00302 }
00303 }
00304 else
00305 {
00306 CH_TIME("MultilevelLinearOp::preCond::LevelBased");
00307
00308
00309 for (int level = m_lBase; level < numLevels; level++)
00310 {
00311 m_vectOperators[level]->preCond(*a_cor[level], *a_residual[level]);
00312 }
00313 }
00314 }
00315
00316
00318
00323 template<class T>
00324 void
00325 MultilevelLinearOp<T>::applyOp(Vector<LevelData<T>* >& a_lhs,
00326 const Vector<LevelData<T>* >& a_phi,
00327 bool a_homogeneous)
00328 {
00329 CH_TIME("MultilevelLinearOp::applyOp");
00330
00331 int numLevels = a_phi.size();
00332 int maxLevel = numLevels-1;
00333 LevelData<T> dummyLDF;
00334 for (int level = m_lBase; level<numLevels; level++)
00335 {
00336 if (level == 0)
00337 {
00338 if (level < maxLevel)
00339 {
00340 m_vectOperators[level]->AMROperatorNC(*a_lhs[level],
00341 *a_phi[level+1],
00342 *a_phi[level],
00343 a_homogeneous,
00344 m_vectOperators[level+1].operator->());
00345 }
00346 else
00347 {
00348
00349 m_vectOperators[level]->applyOp(*a_lhs[level],
00350 *a_phi[level],
00351 a_homogeneous);
00352 }
00353 }
00354 else
00355 {
00356
00357 if (level < maxLevel)
00358 {
00359 m_vectOperators[level]->AMROperator(*a_lhs[level],
00360 *a_phi[level+1],
00361 *a_phi[level],
00362 *a_phi[level-1],
00363 a_homogeneous,
00364 m_vectOperators[level+1].operator->());
00365 }
00366 else
00367 {
00368 m_vectOperators[level]->AMROperatorNF(*a_lhs[level],
00369 *a_phi[level],
00370 *a_phi[level-1],
00371 a_homogeneous);
00372 }
00373 }
00374 }
00375
00376 }
00377
00379
00383 template<class T>
00384 void
00385 MultilevelLinearOp<T>::create(Vector<LevelData<T>* >& a_lhs,
00386 const Vector<LevelData<T>* >& a_rhs)
00387 {
00388 CH_TIME("MultilevelLinearOp::create");
00389
00390 a_lhs.resize(a_rhs.size());
00391
00392 int coarsestLevel = Max(0, m_lBase-1);
00393 for (int level =coarsestLevel; level < a_rhs.size(); level++)
00394 {
00395 a_lhs[level] = new LevelData<T>;
00396 m_vectOperators[level]->create(*a_lhs[level],
00397 *a_rhs[level]);
00398 }
00399 }
00400
00401
00403
00407 template<class T>
00408 void
00409 MultilevelLinearOp<T>::clear(Vector<LevelData<T>* >& a_lhs)
00410 {
00411 CH_TIME("MultilevelLinearOp::clear");
00412
00413 for (int level =0; level < a_lhs.size(); level++)
00414 {
00415 if (a_lhs[level] != NULL)
00416 {
00417 delete a_lhs[level];
00418 a_lhs[level] = NULL;
00419 }
00420 }
00421 }
00422
00423
00425
00428 template<class T>
00429 void
00430 MultilevelLinearOp<T>::assign(Vector<LevelData<T>* >& a_lhs,
00431 const Vector<LevelData<T>* >& a_rhs)
00432 {
00433 CH_TIME("MultilevelLinearOp::assign");
00434
00435 CH_assert (a_lhs.size() == a_rhs.size());
00436
00437 for (int level = m_lBase; level < a_lhs.size(); level++)
00438 {
00439 if (!(a_lhs[level] ==NULL) && !(a_rhs[level] == NULL))
00440 {
00441 m_vectOperators[level]->assign(*a_lhs[level], *a_rhs[level]);
00442 }
00443 }
00444 }
00445
00447
00451 template<class T>
00452 Real
00453 MultilevelLinearOp<T>::dotProduct(const Vector<LevelData<T>* >& a_1,
00454 const Vector<LevelData<T>* >& a_2)
00455 {
00456 CH_TIME("MultilevelLinearOp::dotProduct");
00457
00458
00459 Vector<LevelData<T>* > temp1, temp2;
00460 create(temp1, a_1);
00461 create (temp2, a_2);
00462
00463
00464
00465
00466 setToZero(temp1);
00467 setToZero(temp2);
00468
00469 assign(temp1, a_1);
00470 assign(temp2, a_2);
00471
00472
00473 for (int level =m_lBase; level<temp1.size()-1; level++)
00474 {
00475 LevelData<T>& temp1Level = *temp1[level];
00476 LevelData<T>& temp2Level = *temp2[level];
00477
00478 CH_assert(temp1[level]->getBoxes() == temp2[level]->getBoxes());
00479 CH_assert(temp1[level+1] != NULL);
00480
00481 int nRefFine = m_refRatios[level];
00482 const DisjointBoxLayout& finerGrids = temp1[level+1]->getBoxes();
00483 const DisjointBoxLayout& levelGrids = temp1[level]->getBoxes();
00484 DataIterator levelDit = levelGrids.dataIterator();
00485 LayoutIterator finerLit = finerGrids.layoutIterator();
00486
00487 for (levelDit.begin(); levelDit.ok(); ++levelDit)
00488 {
00489 const Box& thisBox = levelGrids[levelDit];
00490 for (finerLit.begin(); finerLit.ok(); ++finerLit)
00491 {
00492 Box testBox = finerGrids[finerLit];
00493 testBox.coarsen(nRefFine);
00494 testBox &= thisBox;
00495 if (!testBox.isEmpty())
00496 {
00497 temp1Level[levelDit].setVal(0.0, testBox,
00498 0, temp1Level.nComp());
00499
00500 temp2Level[levelDit].setVal(0.0, testBox,
00501 0, temp2Level.nComp());
00502 }
00503 }
00504 }
00505 }
00506
00507
00508 Real prod = 0.0;
00509 for (int level =m_lBase; level<temp1.size(); level++)
00510 {
00511 Real levelProd = m_vectOperators[level]->dotProduct(*temp1[level],
00512 *temp2[level]);
00513
00514
00515 RealVect dxLev = m_vectDx[level];
00516 Real scale = D_TERM(dxLev[0], *dxLev[1], *dxLev[2]);
00517 levelProd *= scale;
00518 prod += levelProd;
00519 }
00520
00521 clear(temp1);
00522 clear (temp2);
00523
00524 return prod;
00525 }
00526
00528
00531 template<class T>
00532 void
00533 MultilevelLinearOp<T>::incr (Vector<LevelData<T>* >& a_lhs,
00534 const Vector<LevelData<T>* >& a_x,
00535 Real a_scale)
00536 {
00537 CH_TIME("MultilevelLinearOp::incr");
00538
00539
00540 for (int level=m_lBase; level<a_lhs.size(); level++)
00541 {
00542 m_vectOperators[level]->incr(*a_lhs[level], *a_x[level], a_scale);
00543 }
00544 }
00545
00547
00550 template<class T>
00551 void
00552 MultilevelLinearOp<T>::axby(Vector<LevelData<T>* >& a_lhs,
00553 const Vector<LevelData<T>* >& a_x,
00554 const Vector<LevelData<T>* >& a_y,
00555 Real a_a,
00556 Real a_b)
00557 {
00558 CH_TIME("MultilevelLinearOp::axby");
00559
00560
00561 for (int level=m_lBase; level<a_lhs.size(); ++level)
00562 {
00563 m_vectOperators[level]->axby(*a_lhs[level],
00564 *a_x[level],
00565 *a_y[level],
00566 a_a, a_b);
00567 }
00568 }
00569
00571
00574 template<class T>
00575 void
00576 MultilevelLinearOp<T>::scale(Vector<LevelData<T>* >& a_lhs,
00577 const Real& a_scale)
00578 {
00579 CH_TIME("MultilevelLinearOp::scale");
00580
00581
00582 for (int level =m_lBase; level<a_lhs.size(); level++)
00583 {
00584 m_vectOperators[level]->scale(*a_lhs[level], a_scale);
00585 }
00586
00587 }
00588
00590
00594 template<class T>
00595 Real
00596 MultilevelLinearOp<T>::norm(const Vector<LevelData<T>* >& a_rhs,
00597 int a_ord)
00598 {
00599 CH_TIME("MultilevelLinearOp::norm");
00600
00601
00602 int maxLevel = a_rhs.size()-1;
00603 Real thisNorm = 0.0;
00604 for (int level = m_lBase; level<a_rhs.size(); level++)
00605 {
00606 Real normLevel;
00607
00608 if (level < maxLevel)
00609 {
00610
00611 int refRatio = m_refRatios[level];
00612 normLevel = m_vectOperators[level]->AMRNorm(*a_rhs[level],
00613 *a_rhs[level+1],
00614 refRatio,
00615 a_ord);
00616 }
00617 else
00618 {
00619
00620 LevelData<T> tempLDF;
00621 int refRatio = -1;
00622 normLevel = m_vectOperators[level]->AMRNorm(*a_rhs[level],
00623 tempLDF,
00624 refRatio,
00625 a_ord);
00626 }
00627
00628
00629
00630 if (a_ord > 2)
00631 {
00632 MayDay::Error("MultilevelLinearOp::norm -- undefined for order > 2");
00633 }
00634
00635 if (a_ord == 2)
00636 {
00637 normLevel = normLevel*normLevel;
00638 }
00639
00640 if (a_ord != 0)
00641 {
00642 thisNorm += normLevel;
00643 }
00644 else if (normLevel > thisNorm)
00645 {
00646 thisNorm = normLevel;
00647 }
00648 }
00649
00650 if (a_ord == 2)
00651 {
00652 thisNorm = sqrt(thisNorm);
00653 }
00654
00655 return thisNorm;
00656 }
00657
00659
00662 template<class T>
00663 void
00664 MultilevelLinearOp<T>::setToZero(Vector<LevelData<T>* >& a_lhs)
00665 {
00666 CH_TIME("MultilevelLinearOp::setToZero");
00667
00668
00669
00670 int coarsestLevel = Max(0, m_lBase-1);
00671 for (int level = coarsestLevel; level< a_lhs.size(); level++)
00672 {
00673 m_vectOperators[level]->setToZero(*a_lhs[level]);
00674 }
00675 }
00676
00677 template<class T>
00678 void
00679 MultilevelLinearOp<T>::write(const Vector<LevelData<T>* >* a_data,
00680 const char* a_filename)
00681 {
00682 #ifdef CH_USE_HDF5
00683 writeVectorLevelName(a_data, &m_refRatios, a_filename);
00684 #else
00685 MayDay::Warning("MultilevelLinearOp<T>::write unimplemented since CH_USE_HDF5 undefined");
00686 #endif
00687 }
00688
00689 #include "NamespaceFooter.H"
00690
00691 #endif