PlayaBICGSTABSolverImpl.hpp
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 #ifndef PLAYA_BICGSTABSOLVER_IMPL_HPP
00043 #define PLAYA_BICGSTABSOLVER_IMPL_HPP
00044 
00045 #include "PlayaBICGSTABSolverDecl.hpp"
00046 #include "PlayaLinearCombinationImpl.hpp"
00047 #include "PlayaSimpleScaledOpDecl.hpp"
00048 #include "PlayaSimpleComposedOpDecl.hpp"
00049 
00050 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00051 #include "PlayaLinearOperatorImpl.hpp"
00052 #include "PlayaLinearSolverBaseImpl.hpp"
00053 #include "PlayaSimpleScaledOpImpl.hpp"
00054 #include "PlayaSimpleComposedOpImpl.hpp"
00055 #include "PlayaSimpleTransposedOpImpl.hpp"
00056 #endif
00057 
00058 
00059 
00060 namespace Playa
00061 {
00062 using namespace Teuchos;
00063 
00064 
00065 /* */
00066 template <class Scalar> inline
00067 BICGSTABSolver<Scalar>
00068 ::BICGSTABSolver(const ParameterList& params)
00069   : KrylovSolver<Scalar>(params) {;}
00070 
00071 /* */
00072 template <class Scalar> inline
00073 BICGSTABSolver<Scalar>::BICGSTABSolver(const ParameterList& params,
00074   const PreconditionerFactory<Scalar>& precond)
00075   : KrylovSolver<Scalar>(params, precond) {;}
00076 
00077 /* Write to a stream  */
00078 template <class Scalar> inline
00079 void BICGSTABSolver<Scalar>::print(std::ostream& os) const 
00080 {
00081   os << description() << "[" << std::endl;
00082   os << this->parameters() << std::endl;
00083   os << "]" << std::endl;
00084 }
00085 
00086     
00087 template <class Scalar> inline
00088 SolverState<Scalar> BICGSTABSolver<Scalar>
00089 ::solveUnprec(const LinearOperator<Scalar>& op,
00090   const Vector<Scalar>& b,
00091   Vector<Scalar>& soln) const
00092 {
00093   int maxiters = this->getMaxiters();
00094   Scalar tol = this->getTol();
00095   int verbosity = this->verb();
00096 
00097   Scalar normOfB = sqrt(b.dot(b));
00098 
00099   /* check for trivial case of zero rhs */
00100   if (normOfB < tol) 
00101   {
00102     soln = b.space().createMember();
00103     soln.zero();
00104     return SolverState<Scalar>(SolveConverged, "RHS was zero", 0, 0.0);
00105   }
00106 
00107   /* check for initial zero residual */
00108   Vector<Scalar> x0 = b.copy();
00109   Vector<Scalar> r0 = b.space().createMember();
00110   Vector<Scalar> tmp = b.space().createMember();
00111 
00112   // r0 =  b - op*x0;
00113   op.apply(x0, tmp);
00114   r0 = b - tmp;
00115   
00116   if (sqrt(r0.dot(r0)) < tol*normOfB) 
00117   {
00118     soln = x0;
00119     return SolverState<Scalar>(SolveConverged, "initial resid was zero", 
00120       0, 0.0);
00121   }
00122 
00123   Vector<Scalar> p0 = r0.copy();
00124   //    p0.randomize();
00125   Vector<Scalar> r0Hat = r0.copy();
00126   Vector<Scalar> xMid = b.space().createMember();
00127   Vector<Scalar> rMid = b.space().createMember();
00128   Vector<Scalar> ArMid = b.space().createMember();
00129   Vector<Scalar> x = b.space().createMember();
00130   Vector<Scalar> r = b.space().createMember();
00131   Vector<Scalar> s = b.space().createMember();
00132   Vector<Scalar> ap = b.space().createMember();
00133 
00134   int myRank = MPIComm::world().getRank();
00135 
00136   Scalar resid = -1.0;
00137 
00138   for (int k=1; k<=maxiters; k++)
00139   {
00140     // ap = A*p0
00141     op.apply(p0, ap);
00142 
00143     Scalar den = ap.dot(r0Hat);
00144     if (Utils::chop(sqrt(fabs(den))/normOfB)==0) 
00145     {
00146       SolverState<Scalar> rtn(SolveCrashed, 
00147         "BICGSTAB failure mode 1", k, resid);
00148       return rtn;
00149     }
00150       
00151     Scalar a0 = r0.dot(r0Hat)/den;
00152       
00153     xMid = x0 + a0*p0;
00154     //xMid.axpy(a0, p0, x0);
00155 
00156     rMid = r0 - a0*ap;
00157     //rMid.axpy(-a0, ap, r0);
00158 
00159     // check for convergence
00160     Scalar resid = rMid.norm2()/normOfB;
00161     if (resid < tol) 
00162     {
00163       soln = xMid; 
00164       SolverState<Scalar> rtn(SolveConverged, "yippee!!", k, resid);
00165       return rtn;
00166     }
00167 
00168     // ArMid = A*rMid
00169     op.apply(rMid, ArMid);
00170 
00171     den = ArMid.dot(ArMid);
00172     if (Utils::chop(sqrt(fabs(den))/normOfB)==0)  
00173     {
00174       SolverState<Scalar> rtn(SolveCrashed, 
00175         "BICGSTAB failure mode 2", k, resid);
00176       return rtn;
00177     }
00178 
00179     Scalar w = rMid.dot(ArMid)/den;
00180       
00181     x = xMid + w*rMid;
00182     //x.axpy(w, rMid, xMid);
00183       
00184     r = rMid - w*ArMid;
00185     //r.axpy(-w, ArMid, rMid);
00186 
00187     // check for convergence
00188     resid = sqrt(r.dot(r))/normOfB;
00189     if (resid < tol) 
00190     {
00191       soln = x;
00192       SolverState<Scalar> rtn(SolveConverged, "yippee!!", k, resid);
00193       return rtn;
00194     }
00195 
00196     den = w*(r0.dot(r0Hat));
00197     if (Utils::chop(sqrt(fabs(den))/normOfB)==0) 
00198     {
00199       SolverState<Scalar> rtn(SolveCrashed, 
00200         "BICGSTAB failure mode 3", k, resid);
00201       return rtn;
00202     }
00203     Scalar beta = a0*(r.dot(r0Hat))/den;
00204 
00205     s = p0 - w*ap;
00206     p0 = r + beta*s;
00207 //    p0 = r + beta*p0 - beta*w*ap;
00208     //s.axpy(-w, ap, p0);
00209     //p0.axpy(beta, s, r);
00210 
00211     r0 = r.copy();
00212     x0 = x.copy();
00213 
00214     if (myRank==0 && verbosity > 1 ) 
00215     {
00216       Out::os() << "BICGSTAB: iteration=";
00217       Out::os().width(8);
00218       Out::os() << k;
00219       Out::os().width(20);
00220       Out::os() << " resid=" << resid << std::endl;
00221     }
00222   }
00223     
00224   SolverState<Scalar> rtn(SolveFailedToConverge, 
00225     "BICGSTAB failed to converge", 
00226     maxiters, resid);
00227   return rtn;
00228 }
00229 
00230 
00231 }
00232 
00233 #endif

Site Contact