PlayaBelosSolver.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 "PlayaBelosSolver.hpp"
00044 #include "PlayaPreconditioner.hpp"
00045 #include "PlayaPreconditionerFactory.hpp"
00046 #include "PlayaParameterListPreconditionerFactory.hpp"
00047 
00048 
00049 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00050 #include "PlayaVectorImpl.hpp"
00051 #include "PlayaLinearOperatorImpl.hpp"
00052 #include "PlayaLinearSolverImpl.hpp"
00053 #endif
00054 
00055 using namespace Playa;
00056 using namespace Teuchos;
00057 
00058 
00059 BelosSolver::BelosSolver(const ParameterList& params)
00060   : LinearSolverBase<double>(params), pf_(), hasSolver_(false)
00061 {
00062   if (params.isSublist("Preconditioner"))
00063   {
00064     ParameterList precParams = params.sublist("Preconditioner");
00065     pf_ = new ParameterListPreconditionerFactory(precParams);
00066   }
00067 }
00068 
00069 
00070 
00071 SolverState<double> BelosSolver::solve(const LinearOperator<double>& A, 
00072   const Vector<double>& rhs, 
00073   Vector<double>& soln) const
00074 {
00075   typedef Anasazi::SimpleMV                      MV;
00076   typedef LinearOperator<double>                 OP;
00077   typedef Belos::LinearProblem<double, MV, OP>   LP;
00078 
00079   TEUCHOS_TEST_FOR_EXCEPT(!A.ptr().get());
00080   TEUCHOS_TEST_FOR_EXCEPT(!rhs.ptr().get());
00081 
00082   if (!soln.ptr().get()) 
00083   {
00084     soln = rhs.copy();
00085     /* KRL 8 Jun 2012: set x0 to zero to workaround bug in Belos */
00086     soln.zero();
00087   }
00088 
00089   if (rhs.norm2()==0.0)
00090   {
00091     soln.zero();
00092     SolverStatusCode code = SolveConverged;
00093     SolverState<double> state(code, "Detected trivial solution", 0, 0.0);
00094     
00095     return state;
00096   }
00097 
00098 
00099   RCP<OP> APtr = rcp(new LinearOperator<double>(A));
00100   RCP<MV> bPtr = rcp(new MV(1));
00101   (*bPtr)[0] = rhs;
00102   RCP<MV> ansPtr = rcp(new MV(1));
00103   (*ansPtr)[0] = soln;
00104   
00105   
00106   RCP<LP> prob = rcp(new LP(APtr, ansPtr, bPtr));
00107 
00108   TEUCHOS_TEST_FOR_EXCEPT(!prob->setProblem());
00109 
00110   
00111   if (pf_.ptr().get())
00112   {
00113     Preconditioner<double> P = pf_.createPreconditioner(A);
00114     if (P.hasLeft())
00115     {
00116       prob->setLeftPrec(rcp(new OP(P.left())));
00117     }
00118   
00119     if (P.hasRight())
00120     {
00121       prob->setRightPrec(rcp(new OP(P.right())));
00122     }
00123   }
00124 
00125   if (!hasSolver_)
00126   {
00127 
00128     ParameterList plist = parameters();
00129 
00130     RCP<ParameterList> belosList = rcp(&plist, false);
00131 
00132     std::string solverType = parameters().get<string>("Method");
00133       
00134     if (solverType=="GMRES")
00135     {
00136       solver_=rcp(new Belos::BlockGmresSolMgr<double, MV, OP>(prob, belosList));
00137     }
00138     else if (solverType=="CG")
00139     {
00140       solver_=rcp(new Belos::BlockCGSolMgr<double, MV, OP>(prob, belosList));
00141     }
00142     else if (solverType=="TFQMR")
00143     {
00144       solver_=rcp(new Belos::TFQMRSolMgr<double, MV, OP>(prob, belosList));
00145     }
00146     else if (solverType=="GCRODR")
00147     {
00148       solver_=rcp(new Belos::GCRODRSolMgr<double, MV, OP>(prob, belosList));
00149       hasSolver_ = true; // only cache recycling solvers
00150     }
00151     else if (solverType=="RCG")
00152     {
00153       solver_=rcp(new Belos::RCGSolMgr<double, MV, OP>(prob, belosList));
00154       hasSolver_ = true; // only cache recycling solvers
00155     }
00156     else
00157     {
00158       TEUCHOS_TEST_FOR_EXCEPT(!(solverType=="GMRES" || solverType=="CG"));
00159     }
00160   }
00161   else // reset problem
00162   {
00163     solver_->setProblem( prob );
00164   }
00165   
00166   Belos::ReturnType rtn = solver_->solve();
00167 
00168   int numIters = solver_->getNumIters();
00169   double resid = solver_->achievedTol();
00170   
00171   SolverStatusCode code = SolveFailedToConverge;
00172   if (rtn==Belos::Converged) code = SolveConverged;
00173   SolverState<double> state(code, "Belos solver completed", numIters, resid);
00174   
00175   return state;
00176 }
00177 
00178 
00179 

Site Contact