Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

GenLevelSolverImplem.H

Go to the documentation of this file.
00001 /* _______              __
00002   / ___/ /  ___  __ _  / /  ___
00003  / /__/ _ \/ _ \/  ' \/ _ \/ _ \
00004  \___/_//_/\___/_/_/_/_.__/\___/
00005 */
00006 //
00007 // This software is copyright (C) by the Lawrence Berkeley
00008 // National Laboratory.  Permission is granted to reproduce
00009 // this software for non-commercial purposes provided that
00010 // this notice is left intact.
00011 //
00012 // It is acknowledged that the U.S. Government has rights to
00013 // this software under Contract DE-AC03-765F00098 between
00014 // the U.S.  Department of Energy and the University of
00015 // California.
00016 //
00017 // This software is provided as a professional and academic
00018 // contribution for joint exchange. Thus it is experimental,
00019 // is provided ``as is'', with no warranties of any kind
00020 // whatsoever, no support, no promise of updates, or printed
00021 // documentation. By using this software, you acknowledge
00022 // that the Lawrence Berkeley National Laboratory and
00023 // Regents of the University of California shall have no
00024 // liability with respect to the infringement of other
00025 // copyrights by any part of this software.
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 // using std::cout;
00036 // using std::endl;
00037 
00038 // default constructor
00039 template <class T>
00040 GenLevelSolver<T>::GenLevelSolver()
00041 {
00042   setDefaultValues();
00043 }
00044 
00045 // complete constructor
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 // complete constructor
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 // destructor
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   // coarsen boxes once to start, because coarsest level boxes
00134   // must also be coarsenable (for proper coarse-fine interpolation)
00135   // however, if grid merely covers entire physical domain, then
00136   // want to coarsen all the way down
00137   int nCoarserLevels = -1;
00138 
00139   // (DFM 10/21/02) don't bother doing _any_ of this if m_grids
00140   // is an empty set
00141   if (m_grids.size() > 0)
00142   {
00143     // why do it this way rather than as a dense IVS?
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 // returns GenLevelSolver to a basically undefined state
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   // set this to an invalid value
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 // solve on just this level, homogeneous bcs
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     // initial guess of phi is zero
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     // also initialize oldRes to be initRes;
00269     oldRes[comp] = initRes[comp];
00270 #else
00271     initRes[comp] = 0.0;
00272 #endif
00273 
00274 // if initRes = 0, don't bother solving
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     // compute modified residual LofPhi = res - LNf(corr)
00292     // use homogeneous form of ApplyOp because want to use
00293     // homogeneous CF BC's for correction
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       // DFM (9/20/02) third test is to catch case where
00318       // convergence hangs due to machine precision (or
00319       // solvability) issues.  This follows the approach
00320       // used in AMRSolver
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       // save currentRes into oldRes
00327       oldRes[comp] = currentRes;
00328     } // end loop over components
00329   } // end solver iterations
00330 
00331   // update phi
00332   m_levelOpPtr->sum(a_phi,m_corr);
00333 }
00334 
00335 // solve on just this level, inhomogeneous bcs
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   /* compute initial residual
00347      -- can't use residual() fn because
00348      don't want to zero out higher levels
00349      -- also note that we use LNf,
00350      because this is a LEVEL solve
00351   */
00352 
00353   assert(m_levelOpPtr->isDefined());
00354 
00355   if (a_initializePhiToZero)
00356   {
00357     // initial guess of phi is zero
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     // initialize oldRes to be initRes as well
00377     oldRes[comp] = initRes[comp];
00378 #endif
00379 
00380     // if initRes = 0, don't bother solving
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       // DFM (9/20/02) third test is to catch case where
00420       // convergence hangs due to machine precision (or
00421       // solvability) issues.  This follows the approach
00422       // used in AMRSolver
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       // save currentRes into oldRes
00428       oldRes[comp] = currentRes;
00429     } // end loop over components
00430   } // end solver iterations
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 // set tolerance for stopping due to hung convergence
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

Generated on Wed Apr 16 14:31:05 2003 for EBChombo by doxygen1.2.16