TSFMLOperator.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 /* ***********************************************************************
00003 // 
00004 //           TSFExtended: Trilinos Solver Framework Extended
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // **********************************************************************/
00027 /* @HEADER@ */
00028 
00029 #include "TSFMLOperator.hpp"
00030 #include "Teuchos_Array.hpp"
00031 #include "Teuchos_MPIComm.hpp"
00032 #include "TSFEpetraVector.hpp"
00033 
00034 
00035 
00036 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00037 #include "TSFVectorImpl.hpp"
00038 #include "TSFLinearOperatorImpl.hpp"
00039 #endif
00040 
00041 using namespace TSFExtended;
00042 using namespace Teuchos;
00043 
00044 MLOperator::MLOperator(
00045   const LinearOperator<double>& op,
00046   const ParameterList& mlParams)
00047   : mlPrec_(),
00048     domain_(op.domain().ptr()),
00049     range_(op.range().ptr())
00050 {
00051   Epetra_CrsMatrix& A = EpetraMatrix::getConcrete(op);
00052   
00053   
00054   mlPrec_ = rcp(new ML_Epetra::MultiLevelPreconditioner(A, mlParams));
00055 }
00056 
00057 
00058 void MLOperator::generalApply(const Thyra::EOpTransp M_trans,
00059   const Thyra::VectorBase<double>& x,
00060   Thyra::VectorBase<double>* y,
00061   const double alpha,
00062   const double beta) const
00063 {
00064   /* grab the epetra vector objects underlying the input and output vectors */
00065   const EpetraVector* epIn = dynamic_cast<const EpetraVector*>(&x);
00066   TEST_FOR_EXCEPTION(epIn == 0, std::runtime_error,
00067                      "IfpackOperator apply: input vector is "
00068                      "not an EpetraVector");
00069 
00070   const Epetra_Vector* in = epIn->epetraVec().get();
00071 
00072   EpetraVector* epy = dynamic_cast<EpetraVector*>(y);
00073   TEST_FOR_EXCEPTION(epy == 0, std::runtime_error,
00074                      "IfpackOperator apply: output vector is "
00075                      "not an EpetraVector");
00076 
00077   Epetra_Vector* yy = epy->epetraVec().get();
00078 
00079   /* if beta != 0, we have to create a temporary vector to hold the
00080    * intermediate result beta*y. */
00081   RCP<Thyra::VectorBase<double> > tsfOut;
00082   Epetra_Vector* tmp;
00083 
00084   if (beta!=0.0) /* we need to have storage for the result of op*x */
00085     {
00086       tsfOut = createMember(y->space());
00087       EpetraVector* ep = dynamic_cast<EpetraVector*>(tsfOut.get());
00088       tmp = ep->epetraVec().get();
00089     }
00090   else /* we overwrite y with the application of the op */
00091     {
00092       tmp = yy;
00093     }
00094 
00095 
00096   int ierr;
00097 
00098   /* do the solve (or transpose solve) */
00099   if (M_trans==NOTRANS)
00100     {
00101       ierr = mlPrec_->ApplyInverse(*in, *tmp);
00102     }
00103   else
00104     {
00105       TEST_FOR_EXCEPTION(M_trans != NOTRANS, std::runtime_error,
00106         "ML preconditioner does not support transposes");
00107     }
00108 
00109   /* if necessary, add beta*y */
00110   if (beta != 0.0)
00111     {
00112       /* Compute yy = alpha*tmp + beta*yy */
00113       yy->Update(alpha, *tmp, beta);
00114     }  
00115   else if (alpha != 1.0) /* compute yy = alpha*tmp */
00116     {
00117       /* Because beta != 0.0, an earlier conditional has set tmp=yy. 
00118        * We can therefore do the computation on tmp and it will 
00119        * modify the contents of yy as a side effect. */
00120       tmp->Scale(alpha);
00121     }
00122 
00123   /* At this point, the contents of y should be yy. We are done. */
00124 }
00125   

Site Contact