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 _GENBICGSTABSMOOTHERIMPLEM_H_
00029 #define _GENBICGSTABSMOOTHERIMPLEM_H_
00030
00031 #include "LayoutIterator.H"
00032
00033 template <class T>
00034 GenBiCGStabSmoother<T>::GenBiCGStabSmoother()
00035 {
00036 m_maxIter = 23;
00037 m_solverTol = 1.0e-7;
00038 m_small = 1.0e-60;
00039
00040 m_convergeSmall = 1.0e-2;
00041
00042
00043
00044 m_enableRestart = true;
00045
00046 m_verbose = false;
00047
00048 }
00049
00050 template <class T>
00051 GenBiCGStabSmoother<T>::~GenBiCGStabSmoother()
00052 {
00053 }
00054
00055 template <class T>
00056 GenBiCGStabSmoother<T>* GenBiCGStabSmoother<T>::newBottomSmoother() const
00057 {
00058 GenBiCGStabSmoother* newsmoother = new GenBiCGStabSmoother();
00059 newsmoother->setVerbose(m_verbose);
00060
00061 if (newsmoother == NULL)
00062 {
00063 MayDay::Error("Out of Memory in GenBiCGStabSmoother::newBottomSmoother");
00064 }
00065
00066 return newsmoother;
00067 }
00068
00069 template <class T>
00070 void GenBiCGStabSmoother<T>::setMaxIter(int a_maxIter)
00071 {
00072 m_maxIter = a_maxIter;
00073 }
00074
00075 template <class T>
00076 void GenBiCGStabSmoother<T>::setSolverTol(Real a_solverTol)
00077 {
00078 m_solverTol = a_solverTol;
00079 }
00080
00081 template <class T>
00082 void GenBiCGStabSmoother<T>::setEnableRestart(bool a_enableRestart)
00083 {
00084 m_enableRestart = a_enableRestart;
00085 }
00086
00087 template <class T>
00088 void GenBiCGStabSmoother<T>::setVerbose(bool a_verbose)
00089 {
00090 m_verbose = a_verbose;
00091 }
00092
00093
00094
00095
00096
00097 template <class T>
00098 void GenBiCGStabSmoother<T>::doBottomSmooth(T& a_phi,
00099 const T& a_rhs,
00100 GenSolverOp<T>* a_operatorPtr)
00101 {
00102 bool alreadyRestarted = false;
00103
00104 if (!m_enableRestart) alreadyRestarted =true;
00105 Real small2 = 1.0e-8;
00106
00107 T corremf;
00108 a_operatorPtr->defineOpData(corremf);
00109
00110 T residmf;
00111 a_operatorPtr->defineData(residmf);
00112
00113 T rtwidmf;
00114 a_operatorPtr->defineData(rtwidmf);
00115
00116 T shatmf;
00117 a_operatorPtr->defineOpData(shatmf);
00118
00119 T phatmf;
00120 a_operatorPtr->defineOpData(phatmf);
00121
00122 T pmf;
00123 a_operatorPtr->defineData(pmf);
00124
00125 T vmf;
00126 a_operatorPtr->defineData(vmf);
00127
00128 T tmf;
00129 a_operatorPtr->defineData(tmf);
00130
00131 a_operatorPtr->setToZero(corremf);
00132 a_operatorPtr->setToZero(residmf);
00133 a_operatorPtr->setToZero(rtwidmf);
00134 a_operatorPtr->setToZero(shatmf);
00135 a_operatorPtr->setToZero(phatmf);
00136 a_operatorPtr->setToZero(pmf);
00137 a_operatorPtr->setToZero(vmf);
00138 a_operatorPtr->setToZero(tmf);
00139
00140
00141 a_operatorPtr->applyOpH(a_phi,residmf);
00142 a_operatorPtr->diff(residmf,a_rhs);
00143 a_operatorPtr->negate(residmf);
00144
00145 Real initnorm;
00146 Real oldNorm;
00147 Real rnorm;
00148 Real norms;
00149
00150
00151
00152 initnorm = a_operatorPtr->norm(residmf, 0);
00153 rnorm = initnorm;
00154 oldNorm = initnorm;
00155
00156 if (m_verbose)
00157 {
00158 pout() << "Bottom Smoother initNorm = " << initnorm << endl;
00159 }
00160
00161 a_operatorPtr->copy(rtwidmf,residmf);
00162
00163 Vector<Real> rho;
00164 Vector<Real> alpha;
00165 Vector<Real> omega;
00166
00167 omega.push_back(0.0);
00168 alpha.push_back(0.0);
00169
00170
00171
00172
00173 bool finished = true;
00174
00175 if (initnorm > m_small)
00176 {
00177 finished = false;
00178 }
00179
00180 int iter;
00181 for (iter = 1; iter <= m_maxIter && !finished; iter++)
00182 {
00183 Real rhodot;
00184
00185 bool badDotProd = false;
00186 rhodot = a_operatorPtr->dotProduct(residmf, rtwidmf);
00187
00188 if (Abs(rhodot) < m_small)
00189 {
00190 badDotProd = true;
00191 }
00192
00193 rho.push_back(rhodot);
00194
00195 if (badDotProd)
00196 {
00197 #if FIXIT
00198 for (dit.begin(); dit.ok(); ++dit)
00199 {
00200 a_phi[dit()].plus(corremf[dit()],0,0,ncomp);
00201 }
00202 #endif
00203
00204 if (m_verbose)
00205 {
00206 pout() << "BiCGStabSmoother: BadDotProd -- returning! iter = "
00207 << iter << endl;
00208 }
00209
00210 return;
00211 }
00212
00213
00214
00215 if (iter == 1 || alreadyRestarted)
00216 {
00217 a_operatorPtr->copy(pmf,residmf);
00218 }
00219 else
00220 {
00221 Real betaim1 = (rho[iter-1]/rho[iter-2]) * (alpha[iter-1]/omega[iter-1]);
00222 Real omegaim1 = omega[iter-1];
00223
00224 T temp;
00225 a_operatorPtr->defineData(temp);
00226
00227 a_operatorPtr->copy(temp,vmf);
00228
00229 a_operatorPtr->scalarMul(temp,omegaim1);
00230 a_operatorPtr->negate(temp);
00231
00232 a_operatorPtr->sum(temp,pmf);
00233
00234 a_operatorPtr->scalarMul(temp,betaim1);
00235 a_operatorPtr->sum(temp,residmf);
00236
00237 a_operatorPtr->copy(pmf,temp);
00238 }
00239
00240
00241 #if FIXIT
00242 a_operatorPtr->levelPreconditioner(phatmf, pmf);
00243 #endif
00244
00245
00246 a_operatorPtr->applyOpH(phatmf,vmf);
00247
00248 bool badCorrection = false;
00249 Real denom = a_operatorPtr->dotProduct(vmf, rtwidmf);
00250
00251
00252 Real alphai;
00253
00254 if (Abs(denom) > small2*Abs(rho[iter-1]))
00255 {
00256 alphai = rho[iter-1]/denom;
00257 }
00258 else
00259 {
00260 alphai = 0.0;
00261 badCorrection = true;
00262 }
00263
00264 alpha.push_back(alphai);
00265
00266 if (!badCorrection)
00267 {
00268 #if FIXIT
00269
00270 for (dit.begin(); dit.ok(); ++dit)
00271 {
00272 T& rfab = residmf[dit()];
00273 T& vfab = vmf[dit()];
00274 T& phatfab = phatmf[dit()];
00275 T& corrfab = corremf[dit()];
00276
00277 for (int comp = 0; comp < ncomp; comp++)
00278 {
00279
00280 rfab.plus(vfab,-1.0*alpha[comp][iter],comp,comp,1);
00281
00282
00283 corrfab.plus(phatfab,alpha[comp][iter],comp,comp,1);
00284 }
00285
00286 }
00287 #endif
00288 }
00289 else
00290 {
00291
00292
00293 a_operatorPtr->setToZero(residmf);
00294 }
00295
00296
00297 norms = a_operatorPtr->norm(residmf, 0);
00298
00299
00300
00301
00302
00303 bool allDone = true;
00304 if (norms > m_solverTol*initnorm)
00305 {
00306 allDone = false;
00307 }
00308
00309
00310 if (!allDone)
00311 {
00312
00313
00314 #if FIXIT
00315 a_operatorPtr->levelPreconditioner(shatmf, residmf);
00316 #endif
00317
00318
00319 a_operatorPtr->applyOpH(shatmf,tmf);
00320
00321
00322 Real numerw = a_operatorPtr->dotProduct(tmf, residmf);
00323 Real denomw = a_operatorPtr->dotProduct(tmf, tmf);
00324
00325 Real omegai = 0.0;
00326
00327 if (Abs(denomw) > m_small)
00328 {
00329 omegai = numerw/denomw;
00330 }
00331
00332 omega.push_back(omegai);
00333
00334
00335
00336
00337 #if FIXIT
00338 for (dit.begin(); dit.ok(); ++dit)
00339 {
00340 Box fabbox = grids.get(dit());
00341 T& corrfab = corremf[dit()];
00342 T& shatfab = shatmf[dit()];
00343 T& tfab = tmf[dit()];
00344
00345 T ttemp(fabbox, 1);
00346
00347 for (int comp = 0; comp < ncomp; comp++)
00348 {
00349
00350 corrfab.plus(shatfab,omega[comp][iter],comp,comp,1);
00351
00352
00353 residmf[dit()].plus(tfab,-1.0*omega[comp][iter],comp,comp,1);
00354 }
00355
00356 }
00357 #endif
00358
00359
00360
00361
00362
00363
00364
00365 }
00366 else
00367 {
00368
00369
00370 omega.push_back(0.0);
00371 }
00372
00373
00374 allDone = true;
00375
00376 rnorm = a_operatorPtr->norm(residmf, 0);
00377
00378 if (m_verbose && (rnorm > 0))
00379 {
00380 pout() << "BottomSmoother: after " << iter
00381 << " iterations, residnorm = " << rnorm << endl;
00382 }
00383
00384 if ((rnorm > m_solverTol*initnorm) && (Abs(omega[iter]) > m_small))
00385 {
00386 allDone = false;
00387 }
00388
00389
00390 allDone = allDone &&
00391 (((rnorm < m_solverTol*initnorm) && (Abs(omega[iter]) < m_small))
00392 || (rnorm > oldNorm*(1.0-m_convergeSmall)));
00393
00394 oldNorm = rnorm;
00395
00396
00397
00398
00399
00400 if (allDone)
00401 {
00402
00403
00404 a_operatorPtr->setToZero(corremf);
00405
00406 #if FIXIT
00407 for (dit.begin(); dit.ok(); ++dit)
00408 {
00409 a_phi[dit()].plus(corremf[dit()],0,0,ncomp);
00410 }
00411 #endif
00412
00413 a_operatorPtr->applyOpH(a_phi,residmf);
00414 a_operatorPtr->diff(residmf,a_rhs);
00415 a_operatorPtr->negate(residmf);
00416
00417
00418 allDone = true;
00419
00420 rnorm = a_operatorPtr->norm(residmf, 0);
00421
00422 if (rnorm > m_solverTol*initnorm)
00423 {
00424 allDone = false;
00425 }
00426
00427
00428
00429
00430
00431 if (alreadyRestarted || allDone)
00432 {
00433 finished = true;
00434 }
00435 else
00436 {
00437
00438 if (m_verbose)
00439 {
00440 pout() << "Bottom Smoother -- restarting iterations"
00441 << endl;
00442 }
00443 #if FIXIT
00444
00445 for (dit.begin(); dit.ok(); ++dit)
00446 {
00447 rtwidmf[dit()].copy(residmf[dit()],0,0,ncomp);
00448 }
00449 #endif
00450
00451
00452
00453
00454
00455
00456
00457
00458 finished = false;
00459
00460 alreadyRestarted = true;
00461 }
00462
00463 if (finished && m_verbose)
00464 {
00465 pout() << "Bottom Smoother final Norm = " << rnorm << endl;
00466 }
00467 }
00468 }
00469
00470 bool converged = true;
00471 if (rnorm > m_solverTol*initnorm) converged = false;
00472
00473 if (!converged && m_verbose)
00474 {
00475 pout() << "BiCGStabSmoother not Converged! iter = " << iter << endl;
00476 pout() << " resid/initRes = " << rnorm/initnorm << endl;
00477 }
00478 }
00479
00480 #endif