PlayaPCGSolver.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                 Playa: Programmable Linear Algebra
00005 //                 Copyright 2012 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 #include "PlayaPCGSolver.hpp"
00044 #include "PlayaOut.hpp"
00045 #include "PlayaTabs.hpp"
00046 #include "PlayaLinearCombinationImpl.hpp"
00047 #include "PlayaSimpleComposedOpImpl.hpp"
00048 #include <iomanip>
00049 
00050 using std::setw;
00051 
00052 namespace Playa
00053 {
00054 
00055   SolverState<double> PCGSolver::solve(const LinearOperator<double>& A,
00056                const Vector<double>& b,
00057                Vector<double>& x) const
00058   {
00059     if (precFactory_.ptr().get() == 0)
00060       {
00061   return solveUnprec(A, b, x);
00062       }
00063     else
00064       {
00065   SolverState<double> rtn;
00066   Preconditioner<double> prec = precFactory_.createPreconditioner(A);
00067   if (prec.isIdentity())
00068     {
00069       rtn = solveUnprec(A, b, x);
00070     }
00071   else if (prec.isTwoSided())
00072     {
00073       LinearOperator<double> P = prec.left();
00074       LinearOperator<double> Q = prec.right();
00075       LinearOperator<double> PAQ = P*A*Q;
00076       Vector<double> Pb = P*b;
00077       Vector<double> y;
00078       rtn = solveUnprec(PAQ, Pb, y);
00079       x = Q*y;
00080     }
00081   else if (prec.hasRight())
00082     {
00083       LinearOperator<double> Q = prec.right();
00084       LinearOperator<double> AQ = A*Q;
00085       Vector<double> y;
00086       rtn = solveUnprec(AQ, b, y);
00087       x = Q*y;
00088     }
00089   else if (prec.hasLeft())
00090     {
00091       LinearOperator<double> P = prec.left();
00092       LinearOperator<double> PA = P*A;
00093       Vector<double> Pb = P*b;
00094       rtn = solveUnprec(PA, Pb, x);
00095     }
00096   else
00097     {
00098       TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00099                "Inconsistent preconditioner state "
00100                "in PGCSolver::solve()");
00101     }
00102   return rtn;
00103       }
00104   }
00105   
00106   SolverState<double> PCGSolver::solveUnprec(const LinearOperator<double>& A,
00107                const Vector<double>& b,
00108                Vector<double>& x) const
00109   {
00110     Tabs tab0;
00111     const ParameterList& params = parameters();
00112     int verb = 0;
00113     if (params.isParameter("Verbosity"))
00114       {
00115   verb = getParameter<int>(params, "Verbosity");
00116       }
00117 
00118     int maxIters = getParameter<int>(params, "Max Iterations");
00119     double tol = getParameter<double>(params, "Tolerance");
00120 
00121     /* Display diagnostic information if needed */
00122     PLAYA_ROOT_MSG1(verb, tab0 << "Playa CG Solver");
00123     Tabs tab1;
00124     PLAYA_ROOT_MSG2(verb, tab0);
00125     PLAYA_ROOT_MSG2(verb, tab1 << "Verbosity      " << verb);
00126     PLAYA_ROOT_MSG2(verb, tab1 << "Max Iters      " << maxIters);
00127     PLAYA_ROOT_MSG2(verb, tab1 << "Tolerance      " << tol);
00128 
00129     /* if the solution vector isn't initialized, set to RHS */
00130     if (x.ptr().get()==0) x = b.copy();
00131     
00132     Vector<double> r = b - A*x;
00133     Vector<double> p = r.copy();
00134     double bNorm = b.norm2();
00135     PLAYA_ROOT_MSG2(verb, tab1 << "Problem size:  " << b.space().dim());
00136     PLAYA_ROOT_MSG2(verb, tab1 << "||rhs||        " << bNorm);
00137 
00138     /* Prepare the status object to be returned */
00139     SolverState<double> rtn;
00140     bool converged = false;
00141     bool shortcut = false;
00142 
00143     /* Check for zero rhs */
00144     if (bNorm==0.0)
00145       {
00146   PLAYA_ROOT_MSG2(verb, tab1 << "RHS is zero!");
00147   rtn = SolverState<double>(SolveConverged, "Woo-hoo! Zero RHS shortcut", 
00148           0, 0.0);
00149   shortcut = true;
00150       }
00151 
00152     double rNorm = 0.0;
00153     double rtr = r*r;
00154 
00155     if (!shortcut)
00156       {
00157   PLAYA_ROOT_MSG2(verb, tab1 << endl << tab1 << "CG Loop");
00158 
00159   for (int k=0; k<maxIters; k++)
00160     {
00161       Tabs tab2;
00162       Vector<double> Ap = A*p;
00163       double alpha = rtr/(p*Ap);
00164       x += alpha*p;
00165       r -= alpha*Ap;
00166       double rtrNew = r*r;
00167       rNorm = sqrt(rtrNew);
00168       PLAYA_ROOT_MSG2(verb, tab2 << "iter=" << setw(10) 
00169           << k << setw(20) << "||r||=" << rNorm);
00170       /* check relative residual */
00171       if (rNorm < bNorm*tol) 
00172         {
00173     rtn = SolverState<double>(SolveConverged, "Woo-hoo!", 
00174             k, rNorm);
00175     converged = true;
00176     break;
00177         }
00178       double beta = rtrNew/rtr;
00179       rtr = rtrNew;
00180       p = r + beta*p;
00181     }
00182       }
00183 
00184     if (!converged && !shortcut)
00185       {
00186   rtn = SolverState<double>(SolveFailedToConverge, 
00187           "CG failed to converge", 
00188           maxIters, rNorm);
00189       }
00190 
00191     PLAYA_ROOT_MSG2(verb, tab0 << endl
00192         << tab0 << "CG finished with status " 
00193         << rtn.stateDescription());
00194     return rtn;
00195   }
00196 
00197 
00198 }

Site Contact