TSFNonlinearOperatorBase.hpp
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 #ifndef TSFNONLINEAROPERATORBASE_HPP
00030 #define TSFNONLINEAROPERATORBASE_HPP
00031 
00032 #include "SundanceDefs.hpp"
00033 #include "SundanceHandleable.hpp"
00034 #include "SundanceOut.hpp"
00035 #include "SundanceObjectWithVerbosity.hpp"
00036 #include "TSFVectorDecl.hpp"
00037 #include "TSFLinearOperatorDecl.hpp"
00038 #include "TSFLinearCombinationDecl.hpp"
00039 
00040 namespace TSFExtended
00041 {
00042 using Thyra::Index;
00043 using namespace Teuchos;
00044 
00045 /** 
00046  * Base class for nonlinear operators
00047  */
00048 template <class Scalar>
00049 class NonlinearOperatorBase 
00050   : public Sundance::Handleable<NonlinearOperatorBase<Scalar> >,
00051     public ObjectWithClassVerbosity<NonlinearOperatorBase<Scalar> >
00052 {
00053 public:
00054   /** Empty ctor, for contexts in which we don't know the
00055    * domain and range spaces at the beginning of construction time */
00056   NonlinearOperatorBase() 
00057     : domain_(), range_(), 
00058       jacobianIsValid_(false),
00059       residualIsValid_(false),
00060       currentEvalPt_(),
00061       currentFunctionValue_(),
00062       currentJ_()
00063     {;}
00064 
00065   /** Construct a nonlinear operator with a domain and range */
00066   NonlinearOperatorBase(const VectorSpace<Scalar>& domain,
00067     const VectorSpace<Scalar>& range) 
00068     : domain_(domain.ptr()), range_(range.ptr()), 
00069       jacobianIsValid_(false),
00070       residualIsValid_(false),
00071       currentEvalPt_(),
00072       currentFunctionValue_(),
00073       currentJ_()
00074     {;}
00075                             
00076   /** Return the domain space */
00077   const RCP<const Thyra::VectorSpaceBase<Scalar> >& domain() const 
00078     {return domain_;}
00079 
00080   /** Return the range space */
00081   const RCP<const Thyra::VectorSpaceBase<Scalar> >& range() const 
00082     {return range_;}
00083 
00084   /** Set the evaluation point */
00085   void setEvalPt(const Vector<Scalar>& x)
00086     {
00087       if (this->verb() >= 1)
00088       {
00089         Out::os() << "NonlinearOperatorBase Setting new eval pt";
00090         if (this->verb() > 3)
00091         {
00092           Out::os() << " to " << std::endl ;
00093           x.print(Out::os());
00094         }
00095         Out::os() << std::endl;
00096       }
00097       jacobianIsValid_ = false;
00098       residualIsValid_ = false;
00099 
00100 //         TEST_FOR_EXCEPTION(!x.space().isCompatible(*domain()),
00101 //                            std::runtime_error,
00102 //                            "evaluation point " << x
00103 //                            << " for nonlinear operator is not in the "
00104 //                            "operator's domain space ");
00105         
00106       currentEvalPt_ = x.copy();
00107     }
00108 
00109   /** Get the current point at which the function is to be 
00110    * evaluated */
00111   const Vector<double>& currentEvalPt() const {return currentEvalPt_;}
00112 
00113   /** Return the Jacobian at the current evaluation point */
00114   LinearOperator<double> getJacobian() const 
00115     {
00116       if (this->verb() > 1)
00117       {
00118         Out::os() << "NonlinearOperatorBase getting Jacobian" << std::endl;
00119       }
00120       if (!jacobianIsValid_)
00121       {
00122         if (this->verb() > 3)
00123         {
00124           Out::os() << "...computing new J and F" << std::endl;
00125         }
00126         currentJ_ 
00127           = computeJacobianAndFunction(currentFunctionValue_);
00128         jacobianIsValid_ = true;
00129         residualIsValid_ = true;
00130       }
00131       else
00132       {
00133         if (this->verb() > 1)
00134         {
00135           Out::os() << "...reusing valid J" << std::endl;
00136         }
00137       }
00138       if (this->verb() > 3)
00139       {
00140         Out::os() << "J is " << std::endl;
00141         currentJ_.print(Out::os());
00142         Out::os() << std::endl;
00143       }
00144       return currentJ_;
00145     }
00146 
00147       
00148 
00149   /** Return the function value at the current evaluation point */
00150   Vector<double> getFunctionValue() const 
00151     {
00152       if (this->verb() > 1)
00153       {
00154         Out::os() << "NonlinearOperatorBase getting function value" << std::endl;
00155       }
00156       if (!residualIsValid_)
00157       {
00158         if (this->verb() > 1)
00159         {
00160           Out::os() << "...computing new F" << std::endl;
00161         }
00162         currentFunctionValue_ = computeFunctionValue();
00163         residualIsValid_ = true;
00164       }
00165       else
00166       {
00167         if (this->verb() > 1)
00168         {
00169           Out::os() << "...reusing valid F" << std::endl;
00170         }
00171       }
00172 
00173       if (this->verb() > 3)
00174       {
00175         Out::os() << "F is " << std::endl;
00176         currentFunctionValue_.print(Out::os());
00177         Out::os() << std::endl;
00178       }
00179       return currentFunctionValue_;
00180     }
00181 
00182 
00183   /** Return an initial guess appropriate to this problem */
00184   virtual Vector<double> getInitialGuess() const = 0 ;
00185 
00186 
00187 protected:
00188 
00189   /** Compute the Jacobian at the current eval point */
00190   virtual LinearOperator<Scalar> computeJacobianAndFunction(Vector<double>& functionValue) const = 0 ;
00191 
00192   /** Compute the function value at the current eval point */
00193   virtual Vector<Scalar> computeFunctionValue() const 
00194     {
00195       computeJacobianAndFunction(currentFunctionValue_);
00196       return currentFunctionValue_;
00197     }
00198 
00199       
00200   /** Set the domain and range. This is protected so that solver
00201    * developers don't try to change the spaces on the fly */
00202   void setDomainAndRange(const VectorSpace<Scalar>& domain,
00203     const VectorSpace<Scalar>& range)
00204     {
00205       domain_ = domain.ptr();
00206       range_ = range.ptr();
00207     }
00208 
00209 
00210 private:
00211   /** */
00212   RCP<const Thyra::VectorSpaceBase<Scalar> > domain_;
00213 
00214   /** */
00215   RCP<const Thyra::VectorSpaceBase<Scalar> > range_;
00216 
00217   /** */
00218   mutable bool jacobianIsValid_;
00219 
00220   /** */
00221   mutable bool residualIsValid_;
00222 
00223   /** */
00224   Vector<double> currentEvalPt_;
00225 
00226   /** */
00227   mutable Vector<double> currentFunctionValue_;
00228 
00229   /** */
00230   mutable LinearOperator<double> currentJ_;
00231 };
00232 
00233 
00234 
00235  
00236 }
00237 
00238 
00239 #endif

Site Contact