void MCMultiGrid::relax (MultiFab& solL, MultiFab& rhsL, int level, Real eps_rel, Real eps_abs, MCBC_Mode bc_mode) { // // Recursively relax system. Equivalent to multigrid V-cycle. // At coarsest grid, call coarsestSmooth. // if (level < numlevels - 1 ) { for (int i = preSmooth() ; i > 0 ; i--) { Lp.smooth(solL, rhsL, level, bc_mode); } Lp.residual(*res[level], rhsL, solL, level, bc_mode); prepareForLevel(level+1); average(*rhs[level+1], *res[level]); cor[level+1]->setVal(0.0); for (int i = cntRelax(); i > 0 ; i--) { relax(*cor[level+1],*rhs[level+1],level+1,eps_rel,eps_abs,bc_mode); } interpolate(solL, *cor[level+1]); for (int i = postSmooth(); i > 0 ; i--) { Lp.smooth(solL, rhsL, level, bc_mode); } } else { coarsestSmooth(solL, rhsL, level, eps_rel, eps_abs, bc_mode); } }
void MultiGrid::coarsestSmooth (MultiFab& solL, MultiFab& rhsL, int level, Real eps_rel, Real eps_abs, LinOp::BC_Mode bc_mode, int local_usecg, Real& cg_time) { BL_PROFILE("MultiGrid::coarsestSmooth()"); prepareForLevel(level); if ( local_usecg == 0 ) { Real error0 = 0; if ( verbose > 0 ) { error0 = errorEstimate(level, bc_mode); if ( ParallelDescriptor::IOProcessor() ) std::cout << " Bottom Smoother: Initial error (error0) = " << error0 << '\n'; } for (int i = finalSmooth(); i > 0; i--) { Lp.smooth(solL, rhsL, level, bc_mode); if ( verbose > 1 || (i == 1 && verbose) ) { Real error = errorEstimate(level, bc_mode); const Real rel_error = (error0 != 0) ? error/error0 : 0; if ( ParallelDescriptor::IOProcessor() ) std::cout << " Bottom Smoother: Iteration " << i << " error/error0 = " << rel_error << '\n'; } } } else { bool use_mg_precond = false; CGSolver cg(Lp, use_mg_precond, level); cg.setMaxIter(maxiter_b); const Real stime = ParallelDescriptor::second(); int ret = cg.solve(solL, rhsL, rtol_b, atol_b, bc_mode); // // The whole purpose of cg_time is to accumulate time spent in CGSolver. // cg_time += (ParallelDescriptor::second() - stime); if ( ret != 0 ) { if ( smooth_on_cg_unstable ) { // // If the CG solver returns a nonzero value indicating // the problem is unstable. Assume this is not an accuracy // issue and pound on it with the smoother. // if ret == 8, then you have failure to converge // if ( ParallelDescriptor::IOProcessor() && (verbose > 0) ) std::cout << "MultiGrid::coarsestSmooth(): CGSolver returns nonzero. Smoothing ...\n"; coarsestSmooth(solL, rhsL, level, eps_rel, eps_abs, bc_mode, 0, cg_time); } else { // // cg failure probably indicates loss of precision accident. // if ret == 8, then you have failure to converge // setting solL to 0 should be ok. // solL.setVal(0); if ( ParallelDescriptor::IOProcessor() && (verbose > 0) ) { std::cout << "MultiGrid::coarsestSmooth(): setting coarse corr to zero" << '\n'; } } } for (int i = 0; i < nu_b; i++) { Lp.smooth(solL, rhsL, level, bc_mode); } } }
void MultiGrid::relax (MultiFab& solL, MultiFab& rhsL, int level, Real eps_rel, Real eps_abs, LinOp::BC_Mode bc_mode, Real& cg_time) { BL_PROFILE("MultiGrid::relax()"); // // Recursively relax system. Equivalent to multigrid V-cycle. // At coarsest grid, call coarsestSmooth. // if ( level < numlevels - 1 ) { if ( verbose > 2 ) { Real rnorm = errorEstimate(level, bc_mode); if (ParallelDescriptor::IOProcessor()) { std::cout << " AT LEVEL " << level << '\n'; std::cout << " DN:Norm before smooth " << rnorm << '\n';; } } for (int i = preSmooth() ; i > 0 ; i--) { Lp.smooth(solL, rhsL, level, bc_mode); } Lp.residual(*res[level], rhsL, solL, level, bc_mode); if ( verbose > 2 ) { Real rnorm = norm_inf(*res[level]); if (ParallelDescriptor::IOProcessor()) std::cout << " DN:Norm after smooth " << rnorm << '\n'; } prepareForLevel(level+1); average(*rhs[level+1], *res[level]); cor[level+1]->setVal(0.0); for (int i = cntRelax(); i > 0 ; i--) { relax(*cor[level+1],*rhs[level+1],level+1,eps_rel,eps_abs,bc_mode,cg_time); } interpolate(solL, *cor[level+1]); if ( verbose > 2 ) { Lp.residual(*res[level], rhsL, solL, level, bc_mode); Real rnorm = norm_inf(*res[level]); if ( ParallelDescriptor::IOProcessor() ) { std::cout << " AT LEVEL " << level << '\n'; std::cout << " UP:Norm before smooth " << rnorm << '\n'; } } for (int i = postSmooth(); i > 0 ; i--) { Lp.smooth(solL, rhsL, level, bc_mode); } if ( verbose > 2 ) { Lp.residual(*res[level], rhsL, solL, level, bc_mode); Real rnorm = norm_inf(*res[level]); if ( ParallelDescriptor::IOProcessor() ) std::cout << " UP:Norm after smooth " << rnorm << '\n'; } } else { if ( verbose > 2 ) { Real rnorm = norm_inf(rhsL); if ( ParallelDescriptor::IOProcessor() ) { std::cout << " AT LEVEL " << level << '\n'; std::cout << " DN:Norm before bottom " << rnorm << '\n'; } } coarsestSmooth(solL, rhsL, level, eps_rel, eps_abs, bc_mode, usecg, cg_time); if ( verbose > 2 ) { Lp.residual(*res[level], rhsL, solL, level, bc_mode); Real rnorm = norm_inf(*res[level]); if ( ParallelDescriptor::IOProcessor() ) std::cout << " UP:Norm after bottom " << rnorm << '\n'; } } }