Stratimikos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Thyra_AmesosLinearOpWithSolve.cpp
Go to the documentation of this file.
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 //
00005 //         Stratimikos: Thyra-based strategies for linear solvers
00006 //                Copyright (2006) Sandia Corporation
00007 //
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 // @HEADER
00042 */
00043 
00044 #include "Thyra_AmesosLinearOpWithSolve.hpp"
00045 #include "Thyra_EpetraThyraWrappers.hpp"
00046 #include "Thyra_MultiVectorStdOps.hpp"
00047 #include "Epetra_MultiVector.h"
00048 #include "Teuchos_TimeMonitor.hpp"
00049 
00050 
00051 namespace Thyra {
00052 
00053 
00054 // Constructors/initializers/accessors
00055 
00056 
00057 AmesosLinearOpWithSolve::AmesosLinearOpWithSolve():
00058   amesosSolverTransp_(Thyra::NOTRANS),
00059   amesosSolverScalar_(1.0)
00060 {}
00061 
00062 
00063 AmesosLinearOpWithSolve::AmesosLinearOpWithSolve(
00064   const Teuchos::RCP<const LinearOpBase<double> > &fwdOp,
00065   const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00066   const Teuchos::RCP<Epetra_LinearProblem> &epetraLP,
00067   const Teuchos::RCP<Amesos_BaseSolver> &amesosSolver,
00068   const EOpTransp amesosSolverTransp,
00069   const double amesosSolverScalar
00070   )
00071 {
00072   this->initialize(fwdOp,fwdOpSrc,epetraLP,amesosSolver,
00073     amesosSolverTransp,amesosSolverScalar);
00074 }
00075 
00076 
00077 void AmesosLinearOpWithSolve::initialize(
00078   const Teuchos::RCP<const LinearOpBase<double> > &fwdOp,
00079   const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc,
00080   const Teuchos::RCP<Epetra_LinearProblem> &epetraLP,
00081   const Teuchos::RCP<Amesos_BaseSolver> &amesosSolver,
00082   const EOpTransp amesosSolverTransp,
00083   const double amesosSolverScalar
00084   )
00085 {
00086 #ifdef TEUCHOS_DEBUG
00087   TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get()==NULL);
00088   TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL);
00089   TEUCHOS_TEST_FOR_EXCEPT(epetraLP.get()==NULL);
00090   TEUCHOS_TEST_FOR_EXCEPT(amesosSolver.get()==NULL);
00091   TEUCHOS_TEST_FOR_EXCEPT(epetraLP->GetLHS()!=NULL);
00092   TEUCHOS_TEST_FOR_EXCEPT(epetraLP->GetRHS()!=NULL);
00093 #endif
00094   fwdOp_ = fwdOp;
00095   fwdOpSrc_ = fwdOpSrc;
00096   epetraLP_ = epetraLP;
00097   amesosSolver_ = amesosSolver;
00098   amesosSolverTransp_ = amesosSolverTransp;
00099   amesosSolverScalar_ = amesosSolverScalar;
00100   const std::string fwdOpLabel = fwdOp_->getObjectLabel();
00101   if(fwdOpLabel.length())
00102     this->setObjectLabel( "lows("+fwdOpLabel+")" );
00103 }
00104 
00105 
00106 Teuchos::RCP<const LinearOpSourceBase<double> >
00107 AmesosLinearOpWithSolve::extract_fwdOpSrc()
00108 {
00109   Teuchos::RCP<const LinearOpSourceBase<double> >
00110     _fwdOpSrc = fwdOpSrc_;
00111   fwdOpSrc_ = Teuchos::null;
00112   return _fwdOpSrc;
00113 }
00114 
00115 
00116 void AmesosLinearOpWithSolve::uninitialize(
00117   Teuchos::RCP<const LinearOpBase<double> > *fwdOp,
00118   Teuchos::RCP<const LinearOpSourceBase<double> > *fwdOpSrc,
00119   Teuchos::RCP<Epetra_LinearProblem> *epetraLP,
00120   Teuchos::RCP<Amesos_BaseSolver> *amesosSolver,
00121   EOpTransp *amesosSolverTransp,
00122   double *amesosSolverScalar
00123   )
00124 {
00125 
00126   if(fwdOp) *fwdOp = fwdOp_;
00127   if(fwdOpSrc) *fwdOpSrc = fwdOpSrc_;
00128   if(epetraLP) *epetraLP = epetraLP_;
00129   if(amesosSolver) *amesosSolver = amesosSolver_;
00130   if(amesosSolverTransp) *amesosSolverTransp = amesosSolverTransp_;
00131   if(amesosSolverScalar) *amesosSolverScalar = amesosSolverScalar_;
00132 
00133   fwdOp_ = Teuchos::null;
00134   fwdOpSrc_ = Teuchos::null;
00135   epetraLP_ = Teuchos::null;
00136   amesosSolver_ = Teuchos::null;
00137   amesosSolverTransp_ = NOTRANS;
00138   amesosSolverScalar_ = 0.0;
00139 
00140 }
00141 
00142 
00143 // Overridden from LinearOpBase
00144 
00145 
00146 Teuchos::RCP< const VectorSpaceBase<double> >
00147 AmesosLinearOpWithSolve::range() const
00148 {
00149   return ( fwdOp_.get() ? fwdOp_->range() : Teuchos::null );
00150 }
00151 
00152 
00153 Teuchos::RCP< const VectorSpaceBase<double> >
00154 AmesosLinearOpWithSolve::domain() const
00155 {
00156   return  ( fwdOp_.get() ? fwdOp_->domain() : Teuchos::null );
00157 }
00158 
00159 
00160 Teuchos::RCP<const LinearOpBase<double> >
00161 AmesosLinearOpWithSolve::clone() const
00162 {
00163   return Teuchos::null; // Not supported yet but could be
00164 }
00165 
00166 
00167 // Overridden from Teuchos::Describable
00168 
00169 
00170 std::string AmesosLinearOpWithSolve::description() const
00171 {
00172   std::ostringstream oss;
00173   oss << Teuchos::Describable::description();
00174   if(!is_null(amesosSolver_)) {
00175     oss
00176       << "{fwdOp="<<fwdOp_->description()
00177       << ",amesosSolver="<<typeName(*amesosSolver_)<<"}";
00178   }
00179   return oss.str();
00180 }
00181 
00182 
00183 void AmesosLinearOpWithSolve::describe(
00184   Teuchos::FancyOStream &out,
00185   const Teuchos::EVerbosityLevel verbLevel
00186   ) const
00187 {
00188   using Teuchos::OSTab;
00189   using Teuchos::typeName;
00190   using Teuchos::describe;
00191   switch(verbLevel) {
00192     case Teuchos::VERB_DEFAULT:
00193     case Teuchos::VERB_LOW:
00194       out << this->description() << std::endl;
00195       break;
00196     case Teuchos::VERB_MEDIUM:
00197     case Teuchos::VERB_HIGH:
00198     case Teuchos::VERB_EXTREME:
00199     {
00200       out
00201         << Teuchos::Describable::description() << "{"
00202         << "rangeDim=" << this->range()->dim()
00203         << ",domainDim="<< this->domain()->dim() << "}\n";
00204       OSTab tab(out);
00205       if(!is_null(fwdOp_)) {
00206         out << "fwdOp = " << describe(*fwdOp_,verbLevel);
00207       }
00208       if(!is_null(amesosSolver_)) {
00209         out << "amesosSolver=" << typeName(*amesosSolver_) << "\n";
00210       }
00211       break;
00212     }
00213     default:
00214       TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here!
00215   }
00216 }
00217 
00218 
00219 // protected
00220 
00221 
00222 // Overridden from LinearOpBase
00223 
00224 
00225 bool AmesosLinearOpWithSolve::opSupportedImpl(EOpTransp M_trans) const
00226 {
00227   return ::Thyra::opSupported(*fwdOp_,M_trans);
00228 }
00229 
00230 
00231 void AmesosLinearOpWithSolve::applyImpl(
00232   const EOpTransp M_trans,
00233   const MultiVectorBase<double> &X,
00234   const Ptr<MultiVectorBase<double> > &Y,
00235   const double alpha,
00236   const double beta
00237   ) const
00238 {
00239   Thyra::apply( *fwdOp_, M_trans, X, Y, alpha, beta );
00240 }
00241 
00242 
00243 // Overridden from LinearOpWithSolveBase
00244 
00245 
00246 bool AmesosLinearOpWithSolve::solveSupportsImpl(EOpTransp M_trans) const
00247 {
00248   if (Thyra::real_trans(M_trans) == Thyra::NOTRANS) {
00249     // Assume every amesos solver supports a basic forward solve!
00250     return true;
00251   }
00252   // Query the amesos solver to see if it supports the transpose operation.
00253   // NOTE: Amesos_BaseSolver makes you change the state of the object to
00254   // determine if the object supports an adjoint solver.  This is a bad design
00255   // but I have no control over that.  This is why you see this hacked
00256   // oldUseTranspose variable and logic.  NOTE: This function meets the basic
00257   // guarantee but if setUseTransplse(...) throws, then the state of
00258   // UseTranspose() may be different.
00259   const bool oldUseTranspose = amesosSolver_->UseTranspose();
00260   const bool supportsAdjoint = (amesosSolver_->SetUseTranspose(true) == 0);
00261   amesosSolver_->SetUseTranspose(oldUseTranspose);
00262   return supportsAdjoint;
00263 }
00264 
00265 
00266 bool AmesosLinearOpWithSolve::solveSupportsSolveMeasureTypeImpl(
00267   EOpTransp M_trans, const SolveMeasureType& solveMeasureType
00268   ) const
00269 {
00270   return true; // I am a direct solver so I should be able to do it all!
00271 }
00272 
00273 
00274 SolveStatus<double>
00275 AmesosLinearOpWithSolve::solveImpl(
00276   const EOpTransp M_trans,
00277   const MultiVectorBase<double> &B,
00278   const Ptr<MultiVectorBase<double> > &X,
00279   const Ptr<const SolveCriteria<double> > solveCriteria
00280   ) const
00281 {
00282   using Teuchos::rcpFromPtr;
00283   using Teuchos::rcpFromRef;
00284   using Teuchos::OSTab;
00285 
00286   Teuchos::Time totalTimer("");
00287   totalTimer.start(true);
00288 
00289   THYRA_FUNC_TIME_MONITOR("Stratimikos: AmesosLOWS");
00290 
00291   Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
00292   Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
00293   OSTab tab = this->getOSTab();
00294   if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_NONE))
00295     *out << "\nSolving block system using Amesos solver "
00296          << typeName(*amesosSolver_) << " ...\n\n";
00297 
00298   //
00299   // Get the op(...) range and domain maps
00300   //
00301   const EOpTransp amesosOpTransp = real_trans(trans_trans(amesosSolverTransp_,M_trans));
00302   const Epetra_Operator *amesosOp = epetraLP_->GetOperator();
00303   const Epetra_Map
00304     &opRangeMap  = ( amesosOpTransp == NOTRANS
00305       ? amesosOp->OperatorRangeMap()  : amesosOp->OperatorDomainMap() ),
00306     &opDomainMap = ( amesosOpTransp == NOTRANS
00307       ? amesosOp->OperatorDomainMap() : amesosOp->OperatorRangeMap()  );
00308 
00309   //
00310   // Get Epetra_MultiVector views of B and X
00311   //
00312   Teuchos::RCP<const Epetra_MultiVector>
00313     epetra_B = get_Epetra_MultiVector(opRangeMap, rcpFromRef(B));
00314   Teuchos::RCP<Epetra_MultiVector>
00315     epetra_X = get_Epetra_MultiVector(opDomainMap, rcpFromPtr(X));
00316 
00317   //
00318   // Set B and X in the linear problem
00319   //
00320   epetraLP_->SetLHS(&*epetra_X);
00321   epetraLP_->SetRHS(const_cast<Epetra_MultiVector*>(&*epetra_B));
00322   // Above should be okay but cross your fingers!
00323 
00324   //
00325   // Solve the linear system
00326   //
00327   const bool oldUseTranspose = amesosSolver_->UseTranspose();
00328   amesosSolver_->SetUseTranspose(amesosOpTransp==TRANS);
00329   const int err = amesosSolver_->Solve();
00330   TEUCHOS_TEST_FOR_EXCEPTION( 0!=err, CatastrophicSolveFailure,
00331     "Error, the function Solve() on the amesos solver of type\n"
00332     "\'"<<typeName(*amesosSolver_)<<"\' failed with error code "<<err<<"!"
00333     );
00334   amesosSolver_->SetUseTranspose(oldUseTranspose);
00335 
00336   //
00337   // Unset B and X
00338   //
00339   epetraLP_->SetLHS(NULL);
00340   epetraLP_->SetRHS(NULL);
00341   epetra_X = Teuchos::null;
00342   epetra_B = Teuchos::null;
00343 
00344   //
00345   // Scale X if needed
00346   //
00347   if(amesosSolverScalar_!=1.0)
00348     Thyra::scale(1.0/amesosSolverScalar_, X);
00349 
00350   //
00351   // Set the solve status if requested
00352   //
00353   SolveStatus<double> solveStatus;
00354   solveStatus.solveStatus = SOLVE_STATUS_CONVERGED;
00355   solveStatus.achievedTol = SolveStatus<double>::unknownTolerance();
00356   solveStatus.message =
00357     std::string("Solver ")+typeName(*amesosSolver_)+std::string(" converged!");
00358 
00359   //
00360   // Report the overall time
00361   //
00362   if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00363     *out
00364       << "\nTotal solve time = "<<totalTimer.totalElapsedTime()<<" sec\n";
00365 
00366   return solveStatus;
00367 
00368 }
00369 
00370 
00371 } // end namespace Thyra
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines