00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011
00012
00013
00014
00015 #ifndef _AMRFASMULTIGRID_H_
00016 #define _AMRFASMULTIGRID_H_
00017
00018 #include "AMRMultiGrid.H"
00019 #include "FASMultiGrid.H"
00020
00021 #include "NamespaceHeader.H"
00022
00023
00024 enum OLD_FASMG_type {FULL=0,VCYCLE=1,FCYCLE=2};
00025
00026
00027
00028
00029
00030 template <class T>
00031 class AMRFASMultiGrid : public AMRMultiGrid<T>
00032 {
00033 public:
00034 AMRFASMultiGrid();
00035 virtual ~AMRFASMultiGrid();
00036
00037 virtual void define(const ProblemDomain& a_coarseDomain,
00038 AMRLevelOpFactory<T>& a_factory,
00039 LinearSolver<T>* a_bottomSolver,
00040 int a_numLevels);
00041
00042 virtual void solveNoInit(Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00043 int l_max, int l_base, bool a_zeroPhi=true,
00044 bool forceHomogeneous = false);
00045
00046 void setCycleType( OLD_FASMG_type a_type )
00047 {
00048 m_type = a_type;
00049 }
00050 void setAvoidNorms( bool b = true )
00051 {
00052 m_avoid_norms = b;
00053 }
00054 void setNumVcycles( int n )
00055 {
00056 m_numVcycles = n;
00057 }
00058
00059
00060 int m_iter;
00061
00062 private:
00063 virtual void FMG(Vector<T*>& a_phi,
00064 const Vector<T*>& a_rhs,
00065 int l, int l_max, int l_base);
00066
00067 virtual void VCycle(Vector<T*>& a_phi,
00068 const Vector<T*>& a_rhs,
00069 int l, int l_max, int l_base);
00070
00071 virtual void init(const Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00072 int l_max, int l_base);
00073
00074 void clear_private();
00075
00076
00077 OLD_FASMG_type m_type;
00078 bool m_avoid_norms;
00079 int m_numVcycles;
00080 Vector<Copier> m_HOCopier;
00081 Vector<Copier> m_revHOCopier;
00082
00083 Vector<Copier> m_HOCornerCopier;
00084 ProblemDomain m_coarseDomain;
00085 };
00086
00087
00088
00089
00090
00091
00092
00093
00094 template <class T>
00095 AMRFASMultiGrid<T>::AMRFASMultiGrid()
00096 : AMRMultiGrid<T>()
00097 {
00098 m_numVcycles = 1;
00099 m_type = VCYCLE;
00100 m_avoid_norms = false;
00101 }
00102
00103
00104
00105
00106 template <class T>
00107 AMRFASMultiGrid<T>::~AMRFASMultiGrid()
00108 {
00109 CH_TIME("~AMRFASMultiGrid");
00110 clear_private();
00111 }
00112
00113
00114
00115
00116 template <class T>
00117 void AMRFASMultiGrid<T>::define( const ProblemDomain& a_coarseDomain,
00118 AMRLevelOpFactory<T>& a_factory,
00119 LinearSolver<T>* a_bottomSolver,
00120 int a_maxAMRLevels )
00121 {
00122 CH_TIME("AMRFASMultiGrid::define");
00123
00124 AMRMultiGrid<T>::define( a_coarseDomain,a_factory,a_bottomSolver,a_maxAMRLevels);
00125
00126 m_HOCopier.resize( a_maxAMRLevels );
00127 m_revHOCopier.resize( a_maxAMRLevels );
00128 m_HOCornerCopier.resize( a_maxAMRLevels );
00129 m_coarseDomain = a_coarseDomain;
00130
00131
00132
00133 ProblemDomain current = a_coarseDomain;
00134 for (int i = 0; i < a_maxAMRLevels; i++)
00135 {
00136
00137
00138 if (this->m_mg[i] != NULL)
00139 {
00140 delete this->m_mg[i];
00141 this->m_mg[i] = NULL;
00142 }
00143
00144
00145 this->m_mg[i]= new FASMultiGrid<T>();
00146 this->m_mg[i]->define(a_factory, &this->m_nosolve, current, this->m_maxDepth, this->m_op[i]);
00147
00148
00149
00150 if (i < a_maxAMRLevels-1)
00151 {
00152 current.refine(a_factory.refToFiner(current));
00153 }
00154 }
00155 }
00156
00157
00158
00159
00160 template <class T>
00161 void AMRFASMultiGrid<T>::init( const Vector<T*>& a_phi, const Vector<T*>& a_rhs,
00162 int l_max, int l_base )
00163 {
00164 CH_TIME("AMRFASMultiGrid::init");
00165
00166 AMRMultiGrid<T>::init( a_phi, a_rhs, l_max,l_base );
00167
00168
00169
00170
00171 ProblemDomain dom = m_coarseDomain;
00172 for (int i = l_base+1; i <= l_max; i++)
00173 {
00174 AMRLevelOp<T>& op = *(this->m_op[i]);
00175 int r = op.refToCoarser();
00176 m_HOCopier[i].define( a_phi[i-1]->disjointBoxLayout(), this->m_resC[i]->disjointBoxLayout(),
00177 a_phi[i-1]->ghostVect() );
00178
00179 m_revHOCopier[i] = m_HOCopier[i];
00180 m_revHOCopier[i].reverse();
00181
00182
00183 m_HOCornerCopier[i].define( this->m_resC[i]->disjointBoxLayout(), this->m_resC[i]->disjointBoxLayout(), dom, this->m_resC[i]->ghostVect(), true );
00184
00185
00186 dom = dom.refine(r);
00187 }
00188 }
00189
00190
00191
00192
00193 template <class T>
00194 void AMRFASMultiGrid<T>::clear_private()
00195 {
00196 CH_TIME("AMRFASMultiGrid::clear_private");
00197
00198 for (int i = 0; i < this->m_op.size(); i++)
00199 {
00200 }
00201 }
00202
00203
00204
00205
00206 template<class T>
00207 void AMRFASMultiGrid<T>::solveNoInit( Vector<T*>& a_phi,
00208 const Vector<T*>& a_rhs,
00209 int l_max, int l_base, bool a_zeroPhi,
00210 bool a_forceHomogeneous)
00211 {
00212 CH_TIMERS("AMRFASMultiGrid::solveNoInit");
00213 CH_TIMER("AMRFASMultiGrid::cycle", vtimer);
00214
00215 bool outputIntermediates = false;
00216
00217 this->setBottomSolver( l_max, l_base );
00218
00219 CH_assert(l_base <= l_max);
00220 CH_assert(a_rhs.size() == a_phi.size());
00221
00222 if (a_zeroPhi)
00223 for (int ilev = l_base; ilev <=l_max; ++ilev)
00224 {
00225 this->m_op[ilev]->setToZero(*(a_phi[ilev]));
00226 }
00227
00228 Real initial_rnorm = 0;
00229 if ( !m_avoid_norms )
00230 {
00231 CH_TIME("Initial AMR Residual");
00232 initial_rnorm = this->computeAMRResidual( a_phi, a_rhs, l_max, l_base );
00233 }
00234
00235 if (this->m_convergenceMetric != 0.)
00236 {
00237 initial_rnorm = this->m_convergenceMetric;
00238 }
00239
00240
00241 this->m_bottomSolver->setConvergenceMetrics(initial_rnorm, this->m_bottomSolverEpsCushion*this->m_eps);
00242
00243 Real rnorm = initial_rnorm;
00244 Real norm_last = 2*initial_rnorm;
00245
00246 int iter=0;
00247 if (this->m_verbosity >= 2 && !m_avoid_norms )
00248 {
00249
00250 pout() << " AMRFASMultiGrid:: iteration = " << iter << ", residual norm = " << rnorm << std::endl;
00251 }
00252
00253 bool goNorm = rnorm > this->m_normThresh || m_avoid_norms;
00254 bool goRedu = rnorm > this->m_eps*initial_rnorm || m_avoid_norms;
00255 bool goIter = iter < this->m_iterMax;
00256 bool goHang = iter < this->m_imin || rnorm <(1-this->m_hang)*norm_last;
00257 bool goMin = iter < this->m_iterMin ;
00258 while (goMin || (goIter && goRedu && goHang && goNorm))
00259 {
00260 norm_last = rnorm;
00261
00262
00263 CH_START(vtimer);
00264 if ( m_type == FULL )
00265 {
00266 FMG( a_phi, a_rhs, l_max, l_max, l_base);
00267 }
00268 else if ( m_type == VCYCLE )
00269 {
00270
00271 this->m_op[l_max]->assignLocal( *(this->m_residual[l_max]), *(a_rhs[l_max]) );
00272 VCycle( a_phi, a_rhs, l_max, l_max, l_base);
00273 }
00274 else
00275 {
00276 MayDay::Error("unknown FAS type");
00277 }
00278 CH_STOP(vtimer);
00279
00280 for (int ilev = l_base; ilev <= l_max; ilev++)
00281 {
00282 if (outputIntermediates)
00283 {
00284 char strcorname[100];
00285 sprintf(strcorname, "amrFASmg.phi.iter.%03d", iter);
00286 string namecor(strcorname);
00287 this->outputAMR(a_phi, namecor, l_max, l_base);
00288 }
00289 }
00290
00291
00292
00293 if (this->m_op[0]->orderOfAccuracy()>2)
00294 {
00295 for (int ilev=l_max; ilev>l_base; ilev--)
00296 {
00297 this->m_op[ilev]->enforceCFConsistency(*a_phi[ilev-1], *a_phi[ilev]);
00298 }
00299 }
00300
00301
00302 iter++;
00303 if ( !m_avoid_norms )
00304 {
00305 rnorm = this->computeAMRResidual( a_phi, a_rhs, l_max, l_base );
00306
00307 if (this->m_verbosity >= 2)
00308 {
00309 pout() << " AMRFASMultiGrid:: iteration = " << iter << ", residual norm = " << rnorm;
00310 if (rnorm > 0.0)
00311 {
00312 pout() << ", rate = " << norm_last/rnorm;
00313 }
00314 pout() << std::endl;
00315 }
00316
00317 goNorm = rnorm > this->m_normThresh;
00318 goRedu = rnorm > this->m_eps*initial_rnorm;
00319 goHang = iter < this->m_imin || rnorm <(1-this->m_hang)*norm_last;
00320 }
00321 goIter = iter < this->m_iterMax;
00322 goMin = iter < this->m_iterMin ;
00323 }
00324
00325 this->m_exitStatus = int(!goRedu) + int(!goIter)*2 + int(!goHang)*4 + int(!goNorm)*8;
00326 if (this->m_verbosity >= 2 && !m_avoid_norms)
00327 {
00328 pout() << " AMRFASMultiGrid:: iteration = " << iter << ", residual norm = " << rnorm << std::endl;
00329 }
00330 if (this->m_verbosity > 1)
00331 {
00332 if (!goIter && goRedu && goNorm)
00333 {
00334 pout() << " AMRFASMultiGrid:: WARNING: Exit because max iteration count exceeded" << std::endl;
00335 }
00336 if (!goHang && goRedu && goNorm)
00337 {
00338 pout() << " AMRFASMultiGrid:: WARNING: Exit because of solver hang" << std::endl;
00339 }
00340 if (this->m_verbosity > 4)
00341 {
00342 pout() << " AMRFASMultiGrid:: exitStatus = " << this->m_exitStatus << std::endl;
00343 }
00344 }
00345
00346
00347
00348 this->m_iter = iter;
00349 }
00350
00351
00352
00353
00354 template<class T>
00355 void AMRFASMultiGrid<T>::FMG( Vector<T*>& a_phi,
00356 const Vector<T*>& a_rhs,
00357 int i, int l_max, int l_base)
00358 {
00359
00360 this->m_op[l_base]->assignLocal( *(this->m_residual[l_base]), *(a_rhs[l_base]) );
00361 this->m_mg[l_base]->oneCycle( *(a_phi[l_base]), *(this->m_residual[l_base]) );
00362
00363 for ( int ilev = l_base+1 ; ilev <= l_max ; ilev++ )
00364 {
00365
00366 this->m_op[ilev]->AMRProlongS_2( *(a_phi[ilev]), *(a_phi[ilev-1]),
00367 *(this->m_resC[ilev]), this->m_revHOCopier[ilev],
00368 this->m_HOCornerCopier[ilev], this->m_op[ilev-1] );
00369
00370 this->m_op[ilev]->assignLocal( *(this->m_residual[ilev]), *(a_rhs[ilev]) );
00371 for (int i=0;i<m_numVcycles;i++)
00372 {
00373 VCycle( a_phi, a_rhs, ilev, l_max, l_base );
00374 }
00375 }
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 template<class T>
00385 void AMRFASMultiGrid<T>::VCycle( Vector<T*>& a_phi,
00386 const Vector<T*>& a_rhs_dummy,
00387 int ilev, int l_max, int l_base )
00388 {
00389 if (ilev == l_base)
00390 {
00391 CH_TIME("AMRFASMultiGrid::VCycle:coarse_grid_solver");
00392
00393
00394 #ifdef FAS_PRINT
00395 this->m_op[ilev]->write(a_phi[ilev],"zh_coarsest_phi_0.hdf5");
00396 this->m_op[ilev]->write(this->m_residual[ilev],"zh_coarsest_rhs.hdf5");
00397 #endif
00398
00399
00400
00401
00402 T* phiCoarsePtr = NULL;
00403 if (l_base > 0)
00404 {
00405 phiCoarsePtr = a_phi[l_base-1];
00406 }
00407 FASMultiGrid<T>* fasMg = dynamic_cast<FASMultiGrid<T>*> (this->m_mg[l_base]);
00408
00409
00410
00411 fasMg->oneCycle( *(a_phi[l_base]), *(this->m_residual[l_base]), phiCoarsePtr);
00412
00413 #ifdef FAS_PRINT
00414 this->m_op[ilev]->write(a_phi[ilev],"zh_coarsest_phi_1.hdf5");
00415 #endif
00416 }
00417 else
00418 {
00419
00420
00421
00422 T* rhs = NULL;
00423
00424
00425
00426
00427
00428 if (ilev == l_max)
00429 {
00430 rhs = a_rhs_dummy[ilev];
00431 }
00432 else
00433 {
00434 rhs = this->m_residual[ilev];
00435 }
00436
00437
00438 #ifdef FAS_PRINT
00439 this->m_op[ilev]->write(this->m_residual[ilev],"za_fine_res_0.hdf5");
00440 this->m_op[ilev]->write(a_phi[ilev],"zb_fine_phi_0.hdf5");
00441 #endif
00442
00443
00444 this->m_op[ilev]->relaxNF( *(a_phi[ilev]), (a_phi[ilev-1]), *rhs, this->m_pre );
00445
00446 #ifdef FAS_PRINT
00447 this->m_op[ilev]->write(this->m_residual[ilev],"za_fine_res_1.hdf5");
00448 this->m_op[ilev]->write(a_phi[ilev],"zb_fine_phi_1.hdf5");
00449 this->m_op[ilev]->residual( *(this->m_correction[ilev]), *a_phi[ilev], *(this->m_residual[ilev]), false);
00450 this->m_op[ilev]->write(this->m_correction[ilev],"zz_fine_res_0.hdf5");
00451 #endif
00452
00453
00454
00455
00456
00457
00458 this->computeAMRResidualLevel(this->m_residual,
00459 a_phi,
00460 a_rhs_dummy,
00461 l_max, l_base, ilev-1,
00462 false);
00463
00464
00465
00466
00467
00468 this->m_op[ilev]->AMRRestrictS(*(this->m_resC[ilev]),
00469 *(a_phi[ilev]),
00470 *(a_phi[ilev]),
00471 *(a_phi[ilev-1]),
00472 *(this->m_correction[ilev]),
00473 true );
00474
00475 #ifdef FAS_PRINT
00476 this->m_op[ilev]->write(a_phi[ilev],"zb_fine_phi_2.hdf5");
00477 this->m_op[ilev-1]->write(this->m_resC[ilev],"zb_coarse_phi_1.hdf5");
00478 #endif
00479
00480
00481 this->m_resC[ilev]->copyTo(this->m_resC[ilev]->interval(), *(a_phi[ilev-1]), a_phi[ilev-1]->interval(), this->m_resCopier[ilev]);
00482
00483
00484
00485
00486
00487 this->m_op[ilev]->AMRRestrictS(*(this->m_resC[ilev]),
00488 *rhs,
00489 *(a_phi[ilev]),
00490 *(a_phi[ilev-1]),
00491 *(this->m_correction[ilev]));
00492
00493
00494 #ifdef FAS_PRINT
00495 this->m_op[ilev]->write(this->m_resC[ilev],"zd_resC.hdf5");
00496 this->m_op[ilev]->write(a_phi[ilev-1],"ze_coarse_phi_2.hdf5");
00497 this->m_op[ilev]->write(this->m_residual[ilev],"za_fine_res_2.hdf5");
00498 #endif
00499
00500
00501
00502
00503 this->m_resC[ilev]->copyTo(this->m_resC[ilev]->interval(), *(this->m_residual[ilev-1]), this->m_residual[ilev-1]->interval(), this->m_resCopier[ilev] );
00504
00505 #ifdef FAS_PRINT
00506 this->m_op[ilev-1]->write(this->m_residual[ilev-1],"zf_coarse_res_1.hdf5");
00507 #endif
00508
00509
00510
00511
00512 T undefined;
00513 this->m_op[ilev-1]->AMROperatorNC( *(this->m_correction[ilev-1]), undefined, *(a_phi[ilev-1]), true, this->m_op[ilev]);
00514
00515 #ifdef FAS_PRINT
00516 this->m_op[ilev-1]->write(this->m_correction[ilev-1],"zf_coarse_Lu.hdf5");
00517 this->m_op[ilev]->write(a_phi[ilev],"zb_fine_phi_3.hdf5");
00518 #endif
00519
00520
00521 this->m_op[ilev-1]->axby( *(this->m_residual[ilev-1]), *(this->m_residual[ilev-1]), *(this->m_correction[ilev-1]), 1.0, 1.0);
00522
00523 #ifdef FAS_PRINT
00524 this->m_op[ilev-1]->write(this->m_residual[ilev-1],"zf_coarse_res_3.hdf5");
00525 #endif
00526
00527 {
00528
00529 T R_u_f;
00530 this->m_op[ilev-1]->create( R_u_f, *a_phi[ilev-1]);
00531 this->m_op[ilev-1]->assignLocal( R_u_f, *(a_phi[ilev-1]) );
00532
00533 for (int img = 0; img < this->m_numMG; img++)
00534 {
00535 VCycle( a_phi, a_rhs_dummy, ilev-1, l_max, l_base );
00536 }
00537
00538 #ifdef FAS_PRINT
00539 this->m_op[ilev-1]->write(a_phi[ilev-1],"zi_coarse_phi_2.hdf5");
00540 #endif
00541
00542
00543 this->m_op[ilev-1]->axby( *this->m_correction[ilev-1], *a_phi[ilev-1], R_u_f, 1.0, -1.0 );
00544 this->m_op[ilev-1]->clear( R_u_f );
00545 }
00546
00547 #ifdef FAS_PRINT
00548 this->m_op[ilev-1]->residual( *(this->m_correction[ilev-1]), *a_phi[ilev-1], *(this->m_residual[ilev-1]), true);
00549 this->m_op[ilev-1]->write(this->m_correction[ilev-1],"zz_coarse_res.hdf5");
00550 #endif
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 this->m_op[ilev]->AMRProlongS( *(a_phi[ilev]), *(this->m_correction[ilev-1]),
00562 *(this->m_resC[ilev]),
00563 this->m_reverseCopier[ilev] );
00564
00565
00566 #ifdef FAS_PRINT
00567 this->m_op[ilev]->write(a_phi[ilev],"zl_fine_phi_1.hdf5");
00568 this->m_op[ilev]->residual( *(this->m_correction[ilev]), *a_phi[ilev], *(this->m_residual[ilev]), false);
00569 this->m_op[ilev]->write(this->m_correction[ilev],"zz_fine_res_1.hdf5");
00570 #endif
00571
00572
00573 this->m_op[ilev]->relaxNF( *(a_phi[ilev]), (a_phi[ilev-1]), *rhs, this->m_post );
00574
00575 #ifdef FAS_PRINT
00576 this->m_op[ilev]->write(a_phi[ilev],"zl_fine_phi_2.hdf5");
00577 this->m_op[ilev]->write(this->m_residual[ilev],"za_fine_res_3.hdf5");
00578 this->m_op[ilev]->write(a_rhs_dummy[ilev],"za_rhs.hdf5");
00579 this->m_op[ilev]->residual( *(this->m_correction[ilev]), *a_phi[ilev], *(this->m_residual[ilev]), false);
00580 this->m_op[ilev]->write(this->m_correction[ilev],"zz_fine_res_2.hdf5");
00581 #endif
00582 }
00583 }
00584
00585 #include "NamespaceFooter.H"
00586
00587 #endif