bool FACPreconditioner::solveSystem( SAMRAIVectorReal<NDIM,double>& u, SAMRAIVectorReal<NDIM,double>& f) { // Initialize the solver, when necessary. const bool deallocate_after_solve = !d_is_initialized; if (deallocate_after_solve) initializeSolverState(u,f); // Set the initial guess to equal zero. u.setToScalar(0.0, /*interior_only*/ false); // Keep track of whether we need to (re-)compute the residual. Because u is // initialized to equal zero, the initial residual is precisely the // right-hand-side vector f. We only need to recompute the residual once we // start modifying the solution vector u. d_recompute_residual = false; // Apply a single FAC cycle. if (d_cycle_type == V_CYCLE && d_num_pre_sweeps == 0) { // V-cycle MG without presmoothing keeps the residual equal to the // initial right-hand-side vector f, so we can simply use that vector // for the residual in the FAC algorithm. FACVCycleNoPreSmoothing(u, f, d_finest_ln); } else { d_f->copyVector(Pointer<SAMRAIVectorReal<NDIM,double> >(&f, false), false); d_r->copyVector(Pointer<SAMRAIVectorReal<NDIM,double> >(&f, false), false); switch (d_cycle_type) { case V_CYCLE: FACVCycle(u, *d_f, d_finest_ln); break; case W_CYCLE: FACWCycle(u, *d_f, d_finest_ln); break; case F_CYCLE: FACFCycle(u, *d_f, d_finest_ln); break; default: TBOX_ERROR(d_object_name << "::solveSystem():\n" << " unrecognized FAC cycle type: " << enum_to_string<MGCycleType>(d_cycle_type) << "." << std::endl); } } // Deallocate the solver, when necessary. if (deallocate_after_solve) deallocateSolverState(); return true; }// solveSystem
void FACPreconditioner::FACFCycle( SAMRAIVectorReal<NDIM,double>& u, SAMRAIVectorReal<NDIM,double>& f, int level_num) { if (level_num == d_coarsest_ln) { // Solve Au = f on the coarsest level. d_fac_strategy->solveCoarsestLevel(u, f, level_num); d_recompute_residual = true; } else { // Smooth the error on the current level. if (d_num_pre_sweeps > 0) { d_fac_strategy->smoothError(u, f, level_num, d_num_pre_sweeps, true, false); d_recompute_residual = true; } // Compute the composite-grid residual on the current level and the next // coarser level, and restrict the residual to the next coarser level. if (d_recompute_residual) { d_fac_strategy->computeResidual(*d_r, u, f, level_num-1, level_num); d_fac_strategy->restrictResidual(*d_r, f, level_num-1); } else { d_fac_strategy->restrictResidual(f, f, level_num-1); } // Recursively call the FAC algorithm. FACWCycle(u, f, level_num-1); FACVCycle(u, f, level_num-1); // Prolong the error from the next coarser level and correct the // solution on level. d_fac_strategy->prolongErrorAndCorrect(u, u, level_num); // Smooth error on level. if (d_num_post_sweeps > 0) { d_fac_strategy->smoothError(u, f, level_num, d_num_post_sweeps, false, true); d_recompute_residual = true; } } return; }// FACFCycle