00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011
00012 #ifndef _FASMULTIGRID_H_
00013 #define _FASMULTIGRID_H_
00014
00015 #include "AMRMultiGrid.H"
00016 #include "MultiGrid.H"
00017
00018
00019 #include "NamespaceHeader.H"
00020
00021 template <class T>
00022 class FASMultiGrid : public MultiGrid<T>
00023 {
00024 public:
00025 FASMultiGrid();
00026 virtual ~FASMultiGrid();
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 virtual void define(MGLevelOpFactory<T>& a_factory,
00041 LinearSolver<T>* a_bottomSolver,
00042 const ProblemDomain& a_domain,
00043 int a_maxDepth = -1,
00044 MGLevelOp<T>* a_finestLevelOp = NULL);
00045
00046
00047
00048
00049
00050
00051
00052
00053 virtual void solve(T& a_phi, const T& a_rhs, Real a_tolerance, int a_maxIterations, int verbosity= 0);
00054
00055
00056
00057
00058
00059
00060 virtual void oneCycle(T& a_e, const T& a_res);
00061 void oneCycle(T& a_e, const T& a_res, T* a_phiCoarse);
00062
00063
00064 virtual void cycle(int a_depth, T& a_correction, const T& a_residual);
00065
00066 protected:
00067
00068 Vector< T* > m_phiCoarse;
00069
00070
00071
00072 };
00073
00074
00075
00076 template <class T>
00077 FASMultiGrid<T>::FASMultiGrid()
00078 : MultiGrid<T>()
00079 {
00080 }
00081
00082
00083
00084 template <class T>
00085 FASMultiGrid<T>::~FASMultiGrid()
00086 {
00087 CH_TIME("~FASMultiGrid");
00088 }
00089
00090 template <class T>
00091 void FASMultiGrid<T>::define(MGLevelOpFactory<T>& a_factory,
00092 LinearSolver<T>* a_bottomSolver,
00093 const ProblemDomain& a_domain,
00094 int a_maxDepth,
00095 MGLevelOp<T>* a_finestOp)
00096 {
00097 MultiGrid<T>::define(a_factory,a_bottomSolver,a_domain, a_maxDepth, a_finestOp);
00098
00099
00100
00101 this->m_homogeneous = false;
00102
00103 }
00104
00105
00106 template <class T>
00107 void FASMultiGrid<T>::solve(T& a_phi, const T& a_rhs, Real a_tolerance, int a_maxIterations, int verbosity)
00108 {
00109 CH_TIME("FASMultiGrid::solve");
00110 this->init(a_phi, a_rhs);
00111
00112 T correction, residual;
00113 this->m_op[0]->create(correction, a_phi);
00114 this->m_op[0]->create(residual, a_rhs);
00115 this->m_op[0]->setToZero(a_phi);
00116 this->m_op[0]->residual(residual, a_phi, a_rhs, false);
00117
00118 Real errorno = this->m_op[0]->norm(residual, 0);
00119 if (verbosity > 2)
00120 {
00121 pout() << "FASmultigrid::solve initial residual = " << errorno << std::endl;
00122 }
00123 Real compval = a_tolerance*errorno;
00124 Real epsilon = 1.0e-16;
00125 compval = Max(compval, epsilon);
00126 Real error = errorno;
00127 int iter = 0;
00128 while ((error > compval) && (error > a_tolerance*errorno) && (iter < a_maxIterations))
00129 {
00130 this->m_op[0]->setToZero(correction);
00131 this->m_op[0]->residual(residual, a_phi, a_rhs, false);
00132 error = this->m_op[0]->norm(residual, 0);
00133 if (verbosity > 3)
00134 {
00135 pout() << "FASMultigrid::solve iter = " << iter << ", residual = " << error << std::endl;
00136 }
00137
00138 this->cycle(0, correction, residual);
00139 this->m_op[0]->incr(a_phi, correction, 1.0);
00140
00141 iter++;
00142 }
00143 if (verbosity > 2)
00144 {
00145 pout() << "FASMultigrid::solve final residual = " << error << std::endl;
00146 }
00147
00148 this->m_op[0]->clear(correction);
00149 this->m_op[0]->clear(residual);
00150 }
00151
00152
00153
00154
00155
00156 template <class T>
00157 void FASMultiGrid<T>::oneCycle(T& a_phi, const T& a_rhs)
00158 {
00159
00160 CH_assert(0);
00161 }
00162
00163 template <class T>
00164 void FASMultiGrid<T>::oneCycle(T& a_phi, const T& a_rhs, T* a_phiCoarse)
00165 {
00166 CH_TIME("FASMultigrid::oneCycle");
00167
00168
00169 m_phiCoarse.resize(this->m_depth);
00170 m_phiCoarse[0] = a_phiCoarse;
00171
00172 for (int depth = 1; depth < this->m_depth; depth++)
00173 {
00174 if (m_phiCoarse[depth-1] == NULL)
00175 {
00176 m_phiCoarse[depth] = NULL;
00177 }
00178 else
00179 {
00180 const T& phiCoarseGridFiner = *m_phiCoarse[depth-1];
00181
00182 m_phiCoarse[depth] = new T();
00183
00184 T scratchCrse;
00185 this->m_op[depth]->create(scratchCrse, phiCoarseGridFiner);
00186 this->m_op[depth]->setToZero(scratchCrse);
00187
00188 this->m_op[depth]->createCoarser(*(m_phiCoarse[depth]), phiCoarseGridFiner, true);
00189 this->m_op[depth]->restrictR(*(m_phiCoarse[depth]), phiCoarseGridFiner);
00190
00191
00192
00193 const DisjointBoxLayout& dbl = m_phiCoarse[depth]->disjointBoxLayout();
00194 const Box& coarseDomBox = dbl.physDomain().domainBox();
00195 if (coarseDomBox.smallEnd() == coarseDomBox.bigEnd())
00196 {
00197 delete m_phiCoarse[depth];
00198 m_phiCoarse[depth] = NULL;
00199 }
00200 }
00201 }
00202
00203
00204 this->cycle(0, a_phi, a_rhs);
00205
00206
00207
00208 for (int i=1; i<m_phiCoarse.size(); i++)
00209 {
00210 if (m_phiCoarse[i]!=NULL)
00211 {
00212 delete m_phiCoarse[i];
00213 m_phiCoarse[i] = NULL;
00214 }
00215 }
00216 }
00217
00218
00219
00220 template <class T>
00221 void FASMultiGrid<T>::cycle(int depth, T& a_phi, const T& a_rhs)
00222 {
00223 CH_TIME("FASMultigrid::cycle");
00224
00225
00226 if (depth == this->m_depth-1)
00227 {
00228 CH_TIME("FASMultigrid::cycle:bottom-solve");
00229
00230
00231 this->m_op[0]->setToZero(*this->m_correction[depth]);
00232 this->m_op[0]->incr(*this->m_correction[depth], a_phi, -1.0);
00233
00234
00235 this->m_op[depth ]->relaxNF(a_phi, m_phiCoarse[depth], a_rhs, this->m_bottom);
00236
00237
00238 this->m_op[0]->incr(*this->m_correction[depth], a_phi, 1.0);
00239
00240
00241 }
00242 else
00243 {
00244 int cycles = this->m_cycle;
00245 if ( cycles < 0 )
00246 {
00247 MayDay::Error("FASMultigrid::cycle - non-V cycle options not implemented");
00248 }
00249 else
00250 {
00251
00252 T phi_coarse, op_coarse;
00253
00254 this->m_op[depth+1]->create(phi_coarse, *(this->m_correction[depth+1]));
00255 this->m_op[depth+1]->setToZero(phi_coarse);
00256
00257
00258 this->m_op[depth+1]->create(op_coarse, *(this->m_correction[depth+1]));
00259 this->m_op[depth+1]->setToZero(op_coarse);
00260
00261
00262
00263 this->m_op[depth]->setToZero( *(this->m_correction[depth]));
00264 this->m_op[depth]->incr(*(this->m_correction[depth]), a_phi, -1.0);
00265
00266
00267 this->m_op[depth ]->relaxNF( a_phi, m_phiCoarse[depth], a_rhs, this->m_pre );
00268
00269
00270
00271
00272 T scratch;
00273 this->m_op[depth]->create(scratch, a_phi);
00274 this->m_op[depth]->setToZero(scratch);
00275
00276 this->m_op[depth]->createCoarser(phi_coarse, a_phi, true);
00277
00278 this->m_op[depth ]->restrictR(phi_coarse, a_phi);
00279
00280
00281
00282
00283 this->m_op[depth+1]->applyOpMg(op_coarse, phi_coarse, m_phiCoarse[depth+1], false);
00284
00285
00286 this->m_op[depth ]->restrictResidual(*(this->m_residual[depth+1]), a_phi, m_phiCoarse[depth], a_rhs, false);
00287
00288
00289 this->m_op[depth+1]->incr(*(this->m_residual[depth+1]), op_coarse, 1.0);
00290
00291 for (int img = 0; img < cycles; img++)
00292 {
00293 cycle(depth+1, phi_coarse, *(this->m_residual[depth+1]));
00294 }
00295
00296
00297 this->m_op[depth ]->prolongIncrement(a_phi, *(this->m_correction[depth+1]));
00298
00299
00300 this->m_op[depth ]->relaxNF(a_phi, m_phiCoarse[depth], a_rhs, this->m_post);
00301
00302
00303
00304 this->m_op[depth]->incr(*(this->m_correction[depth]), a_phi, 1.0);
00305
00306
00307 this->m_op[depth+1]->clear(phi_coarse);
00308 this->m_op[depth+1]->clear(op_coarse);
00309 }
00310 }
00311 }
00312
00313
00314 #include "NamespaceFooter.H"
00315 #endif