Thyra_DefaultInverseLinearOp.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //    Thyra: Interfaces and Support for Abstract Numerical Algorithms
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 #ifndef THYRA_DEFAULT_INVERSE_LINEAR_OP_HPP
00030 #define THYRA_DEFAULT_INVERSE_LINEAR_OP_HPP
00031 
00032 #include "Thyra_DefaultInverseLinearOpDecl.hpp"
00033 #include "Thyra_VectorStdOps.hpp"
00034 #include "Thyra_AssertOp.hpp"
00035 #include "Teuchos_Utils.hpp"
00036 #include "Teuchos_TypeNameTraits.hpp"
00037 
00038 
00039 namespace Thyra {
00040 
00041 
00042 // Constructors/initializers/accessors
00043 
00044 
00045 template<class Scalar>
00046 DefaultInverseLinearOp<Scalar>::DefaultInverseLinearOp()
00047 {}
00048 
00049 
00050 template<class Scalar>
00051 DefaultInverseLinearOp<Scalar>::DefaultInverseLinearOp(
00052   const Teuchos::RCP<LinearOpWithSolveBase<Scalar> > &lows,
00053   const SolveCriteria<Scalar> *fwdSolveCriteria,
00054   const EThrowOnSolveFailure throwOnFwdSolveFailure,
00055   const SolveCriteria<Scalar> *adjSolveCriteria,
00056   const EThrowOnSolveFailure throwOnAdjSolveFailure
00057   )
00058 {
00059   initializeImpl(
00060     lows,fwdSolveCriteria,throwOnFwdSolveFailure
00061     ,adjSolveCriteria,throwOnAdjSolveFailure
00062     );
00063 }
00064 
00065 
00066 template<class Scalar>
00067 DefaultInverseLinearOp<Scalar>::DefaultInverseLinearOp(
00068   const Teuchos::RCP<const LinearOpWithSolveBase<Scalar> > &lows,
00069   const SolveCriteria<Scalar> *fwdSolveCriteria,
00070   const EThrowOnSolveFailure throwOnFwdSolveFailure,
00071   const SolveCriteria<Scalar> *adjSolveCriteria,
00072   const EThrowOnSolveFailure throwOnAdjSolveFailure
00073   )
00074 {
00075   initializeImpl(
00076     lows,fwdSolveCriteria,throwOnFwdSolveFailure
00077     ,adjSolveCriteria,throwOnAdjSolveFailure
00078     );
00079 }
00080 
00081 
00082 template<class Scalar>
00083 void DefaultInverseLinearOp<Scalar>::initialize(
00084   const Teuchos::RCP<LinearOpWithSolveBase<Scalar> > &lows,
00085   const SolveCriteria<Scalar> *fwdSolveCriteria,
00086   const EThrowOnSolveFailure throwOnFwdSolveFailure,
00087   const SolveCriteria<Scalar> *adjSolveCriteria,
00088   const EThrowOnSolveFailure throwOnAdjSolveFailure
00089   )
00090 {
00091   initializeImpl(
00092     lows,fwdSolveCriteria,throwOnFwdSolveFailure
00093     ,adjSolveCriteria,throwOnAdjSolveFailure
00094     );
00095 }
00096 
00097 
00098 template<class Scalar>
00099 void DefaultInverseLinearOp<Scalar>::initialize(
00100   const Teuchos::RCP<const LinearOpWithSolveBase<Scalar> > &lows,
00101   const SolveCriteria<Scalar> *fwdSolveCriteria,
00102   const EThrowOnSolveFailure throwOnFwdSolveFailure,
00103   const SolveCriteria<Scalar> *adjSolveCriteria,
00104   const EThrowOnSolveFailure throwOnAdjSolveFailure
00105   )
00106 {
00107   initializeImpl(
00108     lows,fwdSolveCriteria,throwOnFwdSolveFailure
00109     ,adjSolveCriteria,throwOnAdjSolveFailure
00110     );
00111 }
00112 
00113 
00114 template<class Scalar>
00115 void DefaultInverseLinearOp<Scalar>::uninitialize()
00116 {
00117   lows_.uninitialize();
00118   fwdSolveCriteria_ = Teuchos::null;
00119   adjSolveCriteria_ = Teuchos::null;
00120 }
00121 
00122 
00123 // Overridden form InverseLinearOpBase
00124 
00125 
00126 template<class Scalar>
00127 bool DefaultInverseLinearOp<Scalar>::isLowsConst() const
00128 {
00129   return lows_.isConst();
00130 }
00131 
00132 
00133 template<class Scalar>
00134 Teuchos::RCP<LinearOpWithSolveBase<Scalar> >
00135 DefaultInverseLinearOp<Scalar>::getNonconstLows()
00136 {
00137   return lows_.getNonconstObj();
00138 }
00139 
00140 
00141 template<class Scalar>
00142 Teuchos::RCP<const LinearOpWithSolveBase<Scalar> >
00143 DefaultInverseLinearOp<Scalar>::getLows() const
00144 {
00145   return lows_.getConstObj();
00146 }
00147 
00148 
00149 // Overridden from LinearOpBase
00150 
00151 
00152 template<class Scalar>
00153 Teuchos::RCP< const VectorSpaceBase<Scalar> >
00154 DefaultInverseLinearOp<Scalar>::range() const
00155 {
00156   assertInitialized();
00157   return lows_.getConstObj()->domain();
00158 }
00159 
00160 
00161 template<class Scalar>
00162 Teuchos::RCP< const VectorSpaceBase<Scalar> >
00163 DefaultInverseLinearOp<Scalar>::domain() const
00164 {
00165   assertInitialized();
00166   return lows_.getConstObj()->range();
00167 }
00168 
00169 
00170 template<class Scalar>
00171 Teuchos::RCP<const LinearOpBase<Scalar> >
00172 DefaultInverseLinearOp<Scalar>::clone() const
00173 {
00174   return Teuchos::null; // Not supported yet but could be!
00175 }
00176 
00177 
00178 // Overridden from Teuchos::Describable
00179 
00180                                                 
00181 template<class Scalar>
00182 std::string DefaultInverseLinearOp<Scalar>::description() const
00183 {
00184   assertInitialized();
00185   std::ostringstream oss;
00186   oss
00187     << Teuchos::Describable::description() << "{"
00188     << "lows="<<lows_.getConstObj()->description()
00189     << ",fwdSolveCriteria="<<(fwdSolveCriteria_.get()?"...":"DEFAULT")
00190     << ",adjSolveCriteria="<<(adjSolveCriteria_.get()?"...":"DEFAULT")
00191     << "}";
00192   return oss.str();
00193 }
00194 
00195 
00196 template<class Scalar>
00197 void DefaultInverseLinearOp<Scalar>::describe(
00198   Teuchos::FancyOStream &out,
00199   const Teuchos::EVerbosityLevel verbLevel
00200   ) const
00201 {
00202   using Teuchos::RCP;
00203   using Teuchos::OSTab;
00204   assertInitialized();
00205   OSTab tab(out);
00206   switch(verbLevel) {
00207     case Teuchos::VERB_DEFAULT:
00208     case Teuchos::VERB_LOW:
00209       out << this->description() << std::endl;
00210       break;
00211     case Teuchos::VERB_MEDIUM:
00212     case Teuchos::VERB_HIGH:
00213     case Teuchos::VERB_EXTREME:
00214     {
00215       out
00216         << Teuchos::Describable::description() << "{"
00217         << "rangeDim=" << this->range()->dim()
00218         << ",domainDim=" << this->domain()->dim() << "}:\n";
00219       OSTab tab(out);
00220       out <<  "lows = ";
00221       if(!lows_.getConstObj().get()) {
00222         out << " NULL\n";
00223       }
00224       else {
00225         out << Teuchos::describe(*lows_.getConstObj(),verbLevel);
00226 /*
00227   // ToDo: Implement printing of solve criteria!
00228         out << "fwdSolveCriteria:";
00229         if(fwdSolveCriteria_.get())
00230           OSTab(out).o() << "\n" << *fwdSolveCriteria_;
00231         else
00232           out << " NULL\n";
00233         if(adjSolveCriteria_.get())
00234           OSTab(out).o() << "\n" << *adjSolveCriteria_;
00235         else
00236           out << " NULL\n";
00237 */
00238       }
00239       break;
00240     }
00241     default:
00242       TEST_FOR_EXCEPT(true); // Should never be called!
00243   }
00244 }
00245 
00246 
00247 // protected
00248 
00249 
00250 // Overridden from SingleScalarLinearOpBase
00251 
00252 
00253 template<class Scalar>
00254 bool DefaultInverseLinearOp<Scalar>::opSupported(ETransp M_trans) const
00255 {
00256   assertInitialized();
00257   return solveSupports(*lows_.getConstObj(),M_trans);
00258 }
00259 
00260 
00261 template<class Scalar>
00262 void DefaultInverseLinearOp<Scalar>::apply(
00263   const ETransp M_trans,
00264   const MultiVectorBase<Scalar> &X,
00265   MultiVectorBase<Scalar> *Y,
00266   const Scalar alpha,
00267   const Scalar beta
00268   ) const
00269 {
00270   typedef Teuchos::ScalarTraits<Scalar> ST;
00271   assertInitialized();
00272   TEST_FOR_EXCEPT(Y==NULL);
00273   // ToDo: Put in hooks for propogating verbosity level
00274   //
00275   // Y = alpha*op(M)*X + beta*Y
00276   //
00277   //   =>
00278   //
00279   // Y = beta*Y
00280   // Y += alpha*inv(op(lows))*X
00281   //
00282   Teuchos::RCP<MultiVectorBase<Scalar> >
00283     T;
00284   if(beta==ST::zero()) {
00285     T = Teuchos::rcp(Y,false);
00286   }
00287   else {
00288     T = createMembers(Y->range(),Y->domain()->dim());
00289     scale(beta,Y);
00290   }
00291   //
00292   const SolveCriteria<Scalar>
00293     *solveCriteria
00294     = (
00295       real_trans(M_trans)==NOTRANS
00296       ? fwdSolveCriteria_.get()
00297       : adjSolveCriteria_.get()
00298       );
00299   assign(T.get(), ST::zero()); // Have to initialize before solve!
00300   SolveStatus<Scalar>
00301     solveStatus = Thyra::solve<Scalar>(
00302       *lows_.getConstObj(), M_trans
00303       ,X,&*T
00304       ,solveCriteria
00305       );
00306 
00307   TEST_FOR_EXCEPTION(
00308     solveCriteria && solveStatus.solveStatus!=SOLVE_STATUS_CONVERGED
00309     && ( real_trans(M_trans)==NOTRANS
00310          ? throwOnFwdSolveFailure_==THROW_ON_SOLVE_FAILURE
00311          : throwOnAdjSolveFailure_==THROW_ON_SOLVE_FAILURE )
00312     ,CatastrophicSolveFailure
00313     ,"Error, the LOWS object " << lows_.getConstObj()->description() << " returned an unconverged"
00314     "status of " << toString(solveStatus.solveStatus) << " with the message "
00315     << solveStatus.message << "."
00316     );
00317   //
00318   if(beta==ST::zero()) {
00319     scale(alpha,Y);
00320   }
00321   else {
00322     update( alpha, *T, Y );
00323   }
00324 }
00325 
00326 
00327 // private
00328 
00329 
00330 template<class Scalar>
00331 template<class LOWS>
00332 void DefaultInverseLinearOp<Scalar>::initializeImpl(
00333   const Teuchos::RCP<LOWS> &lows,
00334   const SolveCriteria<Scalar> *fwdSolveCriteria,
00335   const EThrowOnSolveFailure throwOnFwdSolveFailure,
00336   const SolveCriteria<Scalar> *adjSolveCriteria,
00337   const EThrowOnSolveFailure throwOnAdjSolveFailure
00338   )
00339 {
00340   lows_.initialize(lows);
00341   if(fwdSolveCriteria)
00342     fwdSolveCriteria_ = Teuchos::rcp(new SolveCriteria<Scalar>(*fwdSolveCriteria));
00343   else
00344     fwdSolveCriteria_ = Teuchos::null;
00345   if(adjSolveCriteria)
00346     adjSolveCriteria_ = Teuchos::rcp(new SolveCriteria<Scalar>(*adjSolveCriteria));
00347   else
00348     adjSolveCriteria_ = Teuchos::null;
00349   throwOnFwdSolveFailure_ = throwOnFwdSolveFailure;
00350   throwOnAdjSolveFailure_ = throwOnAdjSolveFailure;
00351   const std::string lowsLabel = lows_.getConstObj()->getObjectLabel();
00352   if(lowsLabel.length())
00353     this->setObjectLabel( "inv("+lowsLabel+")" );
00354 }
00355 
00356 
00357 } // end namespace Thyra
00358 
00359 
00360 // Related non-member functions
00361 
00362 
00363 template<class Scalar>
00364 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00365 Thyra::nonconstInverse(
00366   const Teuchos::RCP<LinearOpWithSolveBase<Scalar> > &A,
00367   const SolveCriteria<Scalar> *fwdSolveCriteria,
00368   const EThrowOnSolveFailure throwOnFwdSolveFailure,
00369   const SolveCriteria<Scalar> *adjSolveCriteria,
00370   const EThrowOnSolveFailure throwOnAdjSolveFailure
00371   )
00372 {
00373   return Teuchos::rcp(
00374     new DefaultInverseLinearOp<Scalar>(
00375       A,fwdSolveCriteria,throwOnFwdSolveFailure,
00376       adjSolveCriteria,throwOnAdjSolveFailure
00377       )
00378     );
00379 }
00380 
00381 template<class Scalar>
00382 Teuchos::RCP<Thyra::LinearOpBase<Scalar> >
00383 Thyra::inverse(
00384  const Teuchos::RCP<const LinearOpWithSolveBase<Scalar> > &A,
00385  const SolveCriteria<Scalar> *fwdSolveCriteria,
00386  const EThrowOnSolveFailure throwOnFwdSolveFailure,
00387  const SolveCriteria<Scalar> *adjSolveCriteria,
00388  const EThrowOnSolveFailure throwOnAdjSolveFailure
00389   )
00390 {
00391   return Teuchos::rcp(
00392     new DefaultInverseLinearOp<Scalar>(
00393       A,fwdSolveCriteria,throwOnFwdSolveFailure,
00394       adjSolveCriteria,throwOnAdjSolveFailure
00395       )
00396     );
00397 }
00398 
00399 
00400 #endif  // THYRA_DEFAULT_INVERSE_LINEAR_OP_HPP

Generated on Tue Oct 20 12:47:11 2009 for Thyra Operator Solve Support by doxygen 1.4.7