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 _GENLEVELSOLVERIMPLEM_H_
00029 #define _GENLEVELSOLVERIMPLEM_H_
00030
00031 #include "IntVectSet.H"
00032 #include "parstream.H"
00033 #include "LayoutIterator.H"
00034
00035
00036
00037
00038
00039 template <class T>
00040 GenLevelSolver<T>::GenLevelSolver()
00041 {
00042 setDefaultValues();
00043 }
00044
00045
00046 template <class T>
00047 GenLevelSolver<T>::GenLevelSolver(const DisjointBoxLayout& a_grids,
00048 const DisjointBoxLayout* a_baseGrids,
00049 const Box& a_domain,
00050 Real a_dxLevel,
00051 int a_nRefCrse,
00052 const GenLevelMGOp<T>* const a_opin,
00053 int a_ncomp)
00054 {
00055 setDefaultValues();
00056
00057 ProblemDomain physdomain(a_domain);
00058 define(a_grids, a_baseGrids, physdomain, a_dxLevel,
00059 a_nRefCrse, a_opin, a_ncomp);
00060 }
00061
00062
00063 template <class T>
00064 GenLevelSolver<T>::GenLevelSolver(const DisjointBoxLayout& a_grids,
00065 const DisjointBoxLayout* a_baseGrids,
00066 const ProblemDomain& a_domain,
00067 Real a_dxLevel,
00068 int a_nRefCrse,
00069 const GenLevelMGOp<T>* const a_opin,
00070 int a_ncomp)
00071 {
00072 setDefaultValues();
00073
00074 define(a_grids, a_baseGrids, a_domain, a_dxLevel,
00075 a_nRefCrse, a_opin, a_ncomp);
00076 }
00077
00078
00079 template <class T>
00080 GenLevelSolver<T>::~GenLevelSolver()
00081 {
00082 clearMemory();
00083 }
00084
00085 template <class T>
00086 bool GenLevelSolver<T>::isDefined() const
00087 {
00088 return m_isDefined;
00089 }
00090
00091 template <class T>
00092 void GenLevelSolver<T>::define(const DisjointBoxLayout& a_grids,
00093 const DisjointBoxLayout* a_baseGrids,
00094 const Box& a_domain,
00095 Real a_dxLevel,
00096 int a_nRefCrse,
00097 const GenLevelMGOp<T>* const a_opin,
00098 int a_ncomp)
00099 {
00100 ProblemDomain physdomain(a_domain);
00101 define(a_grids, a_baseGrids, a_domain, a_dxLevel, a_nRefCrse,
00102 a_opin, a_ncomp);
00103 }
00104
00105 template <class T>
00106 void GenLevelSolver<T>::define(const DisjointBoxLayout& a_grids,
00107 const DisjointBoxLayout* a_baseGrids,
00108 const ProblemDomain& a_domain,
00109 Real a_dxLevel,
00110 int a_nRefCrse,
00111 const GenLevelMGOp<T>* const a_opin,
00112 int a_ncomp)
00113 {
00114 clearMemory();
00115
00116 m_grids = a_grids;
00117 m_domain = a_domain;
00118 m_dxLevel = a_dxLevel;
00119 m_nRefCrse = a_nRefCrse;
00120
00121 m_resid.define(m_grids, a_ncomp, IntVect::TheZeroVector());
00122 m_scratch.define(m_grids, a_ncomp, IntVect::TheZeroVector());
00123 m_corr.define(m_grids, a_ncomp, IntVect::TheUnitVector());
00124
00125 m_isDefined = true;
00126
00127 m_levelOpPtr = a_opin->newOp();
00128 #if FIXIT
00129 m_levelOpPtr->define(m_grids, a_baseGrids, m_dxLevel,
00130 m_nRefCrse, m_domain, false, a_ncomp);
00131 #endif
00132
00133
00134
00135
00136
00137 int nCoarserLevels = -1;
00138
00139
00140
00141 if (m_grids.size() > 0)
00142 {
00143
00144 IntVectSet ivsCheck(m_domain.domainBox());
00145 LayoutIterator lit = m_grids.layoutIterator();
00146
00147 for (lit.reset(); lit.ok(); ++lit)
00148 {
00149 ivsCheck -= m_grids.get(lit());
00150 }
00151
00152 if (ivsCheck.isEmpty())
00153 {
00154 nCoarserLevels += 1;
00155 }
00156
00157 int refrattot = 2;
00158 bool getOut = false;
00159 while(!getOut)
00160 {
00161 bool addone = true;
00162 for (lit.reset(); lit.ok(); ++lit)
00163 {
00164 Box blocal = m_grids.get(lit());
00165
00166 if (refine(coarsen(blocal,refrattot),refrattot) != blocal)
00167 {
00168 addone = false;
00169 }
00170
00171 if (!addone)
00172 {
00173 break;
00174 }
00175 }
00176
00177 if (addone)
00178 {
00179 nCoarserLevels += 1;
00180 refrattot *= 2;
00181 }
00182 else
00183 {
00184 getOut = true;
00185 }
00186 }
00187 }
00188
00189 nCoarserLevels = Max(nCoarserLevels, 0);
00190
00191 m_levelMG.define(m_grids, a_baseGrids, m_dxLevel,
00192 m_nRefCrse, m_domain, nCoarserLevels, a_opin, a_ncomp);
00193 }
00194
00195
00196 template <class T>
00197 void GenLevelSolver<T>::clearMemory()
00198 {
00199 if (m_levelOpPtr != NULL)
00200 {
00201 delete m_levelOpPtr;
00202 m_levelOpPtr = NULL;
00203 }
00204 }
00205
00206 template <class T>
00207 void GenLevelSolver<T>::setDefaultValues()
00208 {
00209 m_levelOpPtr = NULL;
00210 m_isDefined = false;
00211
00212 m_nRefCrse = -1;
00213 m_dxLevel = -1.0;
00214
00215 m_maxIter = 33;
00216 m_minIter = 4;
00217
00218 m_tolerance = 1.0e-10;
00219 m_operatorTolerance = 1.0e-4;
00220 #ifdef CH_USE_FLOAT
00221 m_tolerance = sqrt(m_tolerance);
00222 #endif
00223
00224 m_verbose = false;
00225 }
00226
00227
00228 template <class T>
00229 void GenLevelSolver<T>::levelSolveH(T& a_phi,
00230 const T& a_rhs,
00231 bool a_initializePhiToZero)
00232 {
00233 assert(isDefined());
00234 assert(a_phi.nComp() == a_rhs.nComp());
00235 assert(a_phi.nComp() == m_resid.nComp());
00236
00244 assert(m_levelOpPtr->isDefined());
00245
00246 if (a_initializePhiToZero)
00247 {
00248
00249 m_levelOpPtr->setToZero(a_phi);
00250 }
00251
00252 m_levelOpPtr->applyOpH(a_phi, m_resid);
00253 m_levelOpPtr->diff(m_resid,a_rhs);
00254 m_levelOpPtr->negate(m_resid);
00255
00256 m_levelOpPtr->setToZero(m_corr);
00257
00258 Vector<Real> initRes(m_resid.nComp());
00259 Vector<Real> oldRes(m_resid.nComp());
00260
00261 bool done = true;
00262
00263 for (int comp = 0; comp < m_resid.nComp(); comp++)
00264 {
00265 #if FIXIT
00266 Interval thisInterval(comp,comp);
00267 initRes[comp] = norm(m_resid, thisInterval, 0);
00268
00269 oldRes[comp] = initRes[comp];
00270 #else
00271 initRes[comp] = 0.0;
00272 #endif
00273
00274
00275 if (initRes[comp] > 0.01*m_tolerance)
00276 {
00277 done = false;
00278 }
00279 }
00280
00281 if (done)
00282 {
00283 return;
00284 }
00285
00286 int iter = 0;
00287 while (!done)
00288 {
00289 iter++;
00290
00291
00292
00293
00294 m_levelMG.mgRelax(m_corr, m_resid, true);
00295
00296 m_levelOpPtr->applyOpH(m_corr, m_scratch);
00297 m_levelOpPtr->diff(m_scratch,m_resid);
00298 m_levelOpPtr->negate(m_scratch);
00299
00300 done = true;
00301 for (int comp = 0; comp < m_scratch.nComp(); comp++)
00302 {
00303 #if FIXIT
00304 Interval thisInterval(comp,comp);
00305 Real currentRes = norm(m_scratch, thisInterval, 0);
00306 #else
00307 Real currentRes = 0.0;
00308 #endif
00309
00310 if (m_verbose)
00311 {
00312 pout() << "iteration #= " << iter
00313 << ": Max(res) = " << currentRes
00314 << endl;
00315 }
00316
00317
00318
00319
00320
00321 done = done &&
00322 ((iter > m_maxIter)
00323 || (currentRes <= m_tolerance*initRes[comp])
00324 || ((iter < m_minIter) && ((currentRes/oldRes[comp]) > 1.0-m_operatorTolerance)));
00325
00326
00327 oldRes[comp] = currentRes;
00328 }
00329 }
00330
00331
00332 m_levelOpPtr->sum(a_phi,m_corr);
00333 }
00334
00335
00336 template <class T>
00337 void GenLevelSolver<T>::levelSolve(T& a_phi,
00338 const T* a_phic,
00339 const T& a_rhs,
00340 bool a_initializePhiToZero)
00341 {
00342 assert(isDefined());
00343 assert(a_phi.nComp() == a_rhs.nComp());
00344 assert(a_phi.nComp() == m_resid.nComp());
00345
00346
00347
00348
00349
00350
00351
00352
00353 assert(m_levelOpPtr->isDefined());
00354
00355 if (a_initializePhiToZero)
00356 {
00357
00358 m_levelOpPtr->setToZero(a_phi);
00359 }
00360
00361 m_levelOpPtr->applyOpI(a_phi, a_phic, m_resid);
00362 m_levelOpPtr->negDiff(m_resid,a_rhs);
00363
00364 m_levelOpPtr->setToZero(m_corr);
00365
00366 Vector<Real> initRes(m_resid.nComp());
00367 Vector<Real> oldRes(m_resid.nComp());
00368
00369 bool done = true;
00370
00371 for (int comp = 0; comp < m_resid.nComp(); comp++)
00372 {
00373 Interval thisInterval(comp,comp);
00374 #if FIXIT
00375 initRes[comp] = norm(m_resid, thisInterval, 0);
00376
00377 oldRes[comp] = initRes[comp];
00378 #endif
00379
00380
00381 if (initRes[comp] > 0.01*m_tolerance)
00382 {
00383 done = false;
00384 }
00385 }
00386
00387 if (done)
00388 {
00389 return;
00390 }
00391
00392 int iter = 0;
00393 while (!done)
00394 {
00395 m_levelMG.mgRelax(m_corr, m_resid, true);
00396
00397 m_levelOpPtr->applyOpH(m_corr, m_scratch);
00398 m_levelOpPtr->negDiff(m_scratch,m_resid);
00399
00400 iter++;
00401
00402 done = true;
00403 for (int comp = 0; comp < m_resid.nComp(); comp++)
00404 {
00405 Real currentRes = 0.0;
00406 Interval thisInterval(comp,comp);
00407
00408 #if FIXIT
00409 currentRes = norm(m_scratch, thisInterval, 0);
00410 #endif
00411
00412 if (m_verbose)
00413 {
00414 pout() << "iteration #= " << iter
00415 << ": Max(res) = " << currentRes
00416 << endl;
00417 }
00418
00419
00420
00421
00422
00423 done = done &&
00424 ((iter > m_maxIter)
00425 || (currentRes <= m_tolerance*initRes[comp] )
00426 || ((iter > m_minIter) && ((currentRes/oldRes[comp]) > 1.0-m_operatorTolerance)));
00427
00428 oldRes[comp] = currentRes;
00429 }
00430 }
00431
00432 m_levelOpPtr->sum(a_phi,m_corr);
00433 }
00434
00435 template <class T>
00436 void GenLevelSolver<T>::setTolerance(Real a_tolerance)
00437 {
00438 m_tolerance = a_tolerance;
00439 }
00440
00441
00442 template <class T>
00443 void GenLevelSolver<T>::setOperatorTolerance(Real a_operatorTolerance)
00444 {
00445 assert(a_tolerance >= 0.0);
00446
00447 m_operatorTolerance = a_operatorTolerance;
00448 }
00449
00450 template <class T>
00451 void GenLevelSolver<T>::setVerbose(bool a_verbose)
00452 {
00453 m_verbose = a_verbose;
00454 }
00455
00456 template <class T>
00457 void GenLevelSolver<T>::setMaxIter(int a_maxIter)
00458 {
00459 m_maxIter = a_maxIter;
00460 }
00461
00462 template <class T>
00463 void GenLevelSolver<T>::setMinIter(int a_minIter)
00464 {
00465 m_minIter = a_minIter;
00466 }
00467
00468 #endif