Beispiel #1
0
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
Beispiel #2
0
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