bool
BJacobiPreconditioner::solveSystem(
    SAMRAIVectorReal<NDIM,double>& x,
    SAMRAIVectorReal<NDIM,double>& b)
{
    // Initialize the preconditioner, when necessary.
    const bool deallocate_after_solve = !d_is_initialized;
    if (deallocate_after_solve) initializeSolverState(x,b);

    Pointer<PatchHierarchy<NDIM> > hierarchy = x.getPatchHierarchy();
    const int coarsest_ln = x.getCoarsestLevelNumber();
    const int   finest_ln = x.getFinestLevelNumber()  ;
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(x.getNumberOfComponents() == b.getNumberOfComponents());
    TBOX_ASSERT(hierarchy == b.getPatchHierarchy());
    TBOX_ASSERT(coarsest_ln == b.getCoarsestLevelNumber());
    TBOX_ASSERT(  finest_ln == b.getFinestLevelNumber()  );
#endif
    const std::string& x_name = x.getName();
    const std::string& b_name = b.getName();
    bool ret_val = true;

    // Zero out the initial guess.
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(d_initial_guess_nonzero == false);
#endif
    x.setToScalar(0.0, /*interior_only*/ false);

    for (int comp = 0; comp < x.getNumberOfComponents(); ++comp)
    {
        // Setup a SAMRAIVectorReal to correspond to the individual vector
        // component.
        std::ostringstream str;
        str << comp;

        SAMRAIVectorReal<NDIM,double> x_comp(x_name+"_component_"+str.str(), hierarchy, coarsest_ln, finest_ln);
        x_comp.addComponent(x.getComponentVariable(comp), x.getComponentDescriptorIndex(comp), x.getControlVolumeIndex(comp));

        SAMRAIVectorReal<NDIM,double> b_comp(b_name+"_component_"+str.str(), hierarchy, coarsest_ln, finest_ln);
        b_comp.addComponent(b.getComponentVariable(comp), b.getComponentDescriptorIndex(comp), b.getControlVolumeIndex(comp));

        // Configure the component preconditioner.
        Pointer<LinearSolver> pc_comp = d_pc_map[comp];
        pc_comp->setInitialGuessNonzero(d_initial_guess_nonzero);
        pc_comp->setMaxIterations(d_max_iterations);
        pc_comp->setAbsoluteTolerance(d_abs_residual_tol);
        pc_comp->setRelativeTolerance(d_rel_residual_tol);

        // Apply the component preconditioner.
        const bool ret_val_comp = pc_comp->solveSystem(x_comp, b_comp);
        ret_val = ret_val && ret_val_comp;
    }

    // Deallocate the preconditioner, when necessary.
    if (deallocate_after_solve) deallocateSolverState();
    return ret_val;
}// solveSystem
Beispiel #2
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
bool BGaussSeidelPreconditioner::solveSystem(SAMRAIVectorReal<NDIM, double>& x, SAMRAIVectorReal<NDIM, double>& b)
{
    // Initialize the preconditioner, when necessary.
    const bool deallocate_after_solve = !d_is_initialized;
    if (deallocate_after_solve) initializeSolverState(x, b);

#if !defined(NDEBUG)
    Pointer<PatchHierarchy<NDIM> > hierarchy = x.getPatchHierarchy();
    const int coarsest_ln = x.getCoarsestLevelNumber();
    const int finest_ln = x.getFinestLevelNumber();
    TBOX_ASSERT(x.getNumberOfComponents() == b.getNumberOfComponents());
    TBOX_ASSERT(hierarchy == b.getPatchHierarchy());
    TBOX_ASSERT(coarsest_ln == b.getCoarsestLevelNumber());
    TBOX_ASSERT(finest_ln == b.getFinestLevelNumber());
#endif
    bool ret_val = true;

// Zero out the initial guess.
#if !defined(NDEBUG)
    TBOX_ASSERT(d_initial_guess_nonzero == false);
#endif
    x.setToScalar(0.0, /*interior_only*/ false);

    // Setup SAMRAIVectorReal objects to correspond to the individual vector
    // components.
    std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > x_comps =
        getComponentVectors(Pointer<SAMRAIVectorReal<NDIM, double> >(&x, false));
    std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > b_comps =
        getComponentVectors(Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false));

    // Clone the right-hand-side vector to avoid modifying it during the
    // preconditioning operation.
    Pointer<SAMRAIVectorReal<NDIM, double> > f = b.cloneVector(b.getName());
    f->allocateVectorData();
    f->copyVector(Pointer<SAMRAIVectorReal<NDIM, double> >(&b, false), false);
    std::vector<Pointer<SAMRAIVectorReal<NDIM, double> > > f_comps = getComponentVectors(f);

    // Setup the order in which the component preconditioner are to be applied.
    const int ncomps = x.getNumberOfComponents();
    std::vector<int> comps;
    comps.reserve(2 * ncomps - 1);
    if (!d_reverse_order)
    {
        // Standard order: Run from comp = 0 to comp = ncomp-1.
        for (int comp = 0; comp < ncomps; ++comp)
        {
            comps.push_back(comp);
        }
        if (d_symmetric_preconditioner)
        {
            for (int comp = ncomps - 2; comp >= 0; --comp)
            {
                comps.push_back(comp);
            }
        }
    }
    else
    {
        // Reversed order: Run from comp = ncomp-1 to comp = 0.
        for (int comp = ncomps - 1; comp >= 0; --comp)
        {
            comps.push_back(comp);
        }
        if (d_symmetric_preconditioner)
        {
            for (int comp = 1; comp < ncomps; ++comp)
            {
                comps.push_back(comp);
            }
        }
    }

    // Apply the component preconditioners.
    int count = 0;
    for (std::vector<int>::const_iterator it = comps.begin(); it != comps.end(); ++it, ++count)
    {
        const int comp = (*it);

        Pointer<SAMRAIVectorReal<NDIM, double> > x_comp = x_comps[comp];
        Pointer<SAMRAIVectorReal<NDIM, double> > b_comp = b_comps[comp];
        Pointer<SAMRAIVectorReal<NDIM, double> > f_comp = f_comps[comp];

        // Update the right-hand-side vector.
        f_comp->setToScalar(0.0);
        for (int c = 0; c < ncomps; ++c)
        {
            if (c == comp) continue;
            d_linear_ops_map[comp][c]->applyAdd(*x_comps[c], *f_comp, *f_comp);
        }
        f_comp->subtract(b_comp, f_comp);

        // Configure the component preconditioner.
        Pointer<LinearSolver> pc_comp = d_pc_map[comp];
        pc_comp->setInitialGuessNonzero(count >= ncomps);
        pc_comp->setMaxIterations(d_max_iterations);
        pc_comp->setAbsoluteTolerance(d_abs_residual_tol);
        pc_comp->setRelativeTolerance(d_rel_residual_tol);

        // Apply the component preconditioner.
        const bool ret_val_comp = pc_comp->solveSystem(*x_comp, *f_comp);
        ret_val = ret_val && ret_val_comp;
    }

    // Free the copied right-hand-side vector data.
    f->deallocateVectorData();
    f->freeVectorComponents();

    // Deallocate the preconditioner, when necessary.
    if (deallocate_after_solve) deallocateSolverState();
    return ret_val;
} // solveSystem