SundanceUnaryFunctor.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 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 #ifndef SUNDANCE_UNARYFUNCTOR_H
00043 #define SUNDANCE_UNARYFUNCTOR_H
00044 
00045 #include "SundanceDefs.hpp"
00046 #include "PlayaExceptions.hpp"
00047 #include "SundanceFunctorDomain.hpp"
00048 #include "Teuchos_ScalarTraits.hpp"
00049 #include "Teuchos_RefCountPtr.hpp"
00050 
00051 #ifndef DOXYGEN_DEVELOPER_ONLY
00052 
00053 namespace Sundance
00054 {
00055   using namespace Teuchos;
00056 
00057   
00058   
00059 
00060   /**
00061    * 
00062    */
00063   class UnaryFunctor
00064   {
00065   public:
00066     /** ctor */
00067     UnaryFunctor(const std::string& name, 
00068                  const RCP<FunctorDomain>& domain 
00069                  = rcp(new UnboundedDomain())) 
00070       : name_(name), h_(fdStep()), domain_(domain) {;}
00071 
00072     /** */
00073     virtual ~UnaryFunctor(){;}
00074 
00075     /** */
00076     const std::string& name() const {return name_;}
00077 
00078     /** */
00079     virtual void eval0(const double* const x, 
00080                        int nx, 
00081                        double* f) const = 0 ;
00082     
00083     /** */
00084     virtual void eval1(const double* const x, 
00085                        int nx, 
00086                        double* f, 
00087                        double* df_dx) const ;
00088     
00089     /** */
00090     virtual void eval2(const double* const x, 
00091                        int nx, 
00092                        double* f, 
00093                        double* df_dx,
00094                        double* d2f_dxx) const ;
00095     
00096     /** */
00097     virtual void eval3(const double* const x, 
00098                        int nx, 
00099                        double* f, 
00100                        double* df_dx,
00101                        double* d2f_dxx,
00102                        double* d3f_dxxx) const ;
00103 
00104     
00105 
00106     /** */
00107     void evalFDDerivs1(const double* const x, 
00108                        int nx, 
00109                        double* f, 
00110                        double* df_dx) const ;
00111     /** */
00112     void evalFDDerivs2(const double* const x, 
00113                        int nx, 
00114                        double* f, 
00115                        double* df_dx,
00116                        double* d2f_dxx) const ;
00117     /** */
00118     void evalFDDerivs3(const double* const x, 
00119                        int nx, 
00120                        double* f, 
00121                        double* df_dx,
00122                        double* d2f_dxx,
00123                        double* d3f_dxxx) const ;
00124 
00125     /** */
00126     bool testDerivs(const double& x, const double& tol) const ;
00127 
00128     /** */
00129     bool testInvalidValue(const double& xBad) const ;
00130 
00131     /** */
00132     bool test(int nx, const double& tol) const ;
00133     
00134     /** Specify whether we should test for NAN or INFINITE results. */
00135     static bool& checkResults() {static bool rtn = false; return rtn;}
00136 
00137     static double& fdStep() {static double rtn = 1.0e-3; return rtn;}
00138 
00139     const RCP<FunctorDomain>& domain() const 
00140     {return domain_;}
00141   private:
00142     std::string name_;
00143 
00144     double h_;
00145 
00146     RCP<FunctorDomain> domain_;
00147   };
00148 }
00149 
00150 /** */
00151 #define SUNDANCE_UNARY_FUNCTOR(opName, functorName, description, domain, \
00152                                funcDefinition, firstDerivDefinition,    \
00153                                secondDerivDefinition)                   \
00154   class functorName : public Sundance::UnaryFunctor                \
00155   {                                                                     \
00156   public:                                                               \
00157     /** ctor for description functor */                                 \
00158     functorName() : Sundance::UnaryFunctor(#opName, rcp(new domain)) {;} \
00159       /** virtual dtor */                                               \
00160       virtual ~functorName(){;}                                         \
00161       /** Evaluate function at an array of values */                    \
00162       void eval0(const double* const x, int nx, double* f) const ;      \
00163       /** Evaluate function and first derivative at an array of values */ \
00164       void eval1(const double* const x,                                 \
00165                  int nx,                                                \
00166                  double* f,                                             \
00167                  double* df) const ;                                    \
00168       /** Evaluate function and first two derivatives at an array of values */ \
00169       void eval2(const double* const x,                                 \
00170                  int nx,                                                \
00171                  double* f,                                             \
00172                  double* df,                                            \
00173                  double* d2f_dxx) const ;                               \
00174   };                                                                    \
00175   inline void functorName::eval0(const double* const x, int nx, double* f) const \
00176   {                                                                     \
00177     if (checkResults())                                                 \
00178       {                                                                 \
00179         for (int i=0; i<nx; i++)                                        \
00180           {                                                             \
00181             f[i] = funcDefinition;                                      \
00182             TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i]), std::runtime_error, "Non-normal floating point result detected in evaluation of unary functor " << name() << " at argument " << x[i]); \
00183           }                                                             \
00184      }                                                                  \
00185    else                                                                 \
00186      {                                                                  \
00187        for (int i=0; i<nx; i++) f[i] = funcDefinition;                  \
00188      }                                                                  \
00189 }                                                                       \
00190   inline void functorName::eval1(const double* const x,                 \
00191                                int nx,                                  \
00192                                double* f,                               \
00193                                double* df) const                        \
00194 {                                                                       \
00195   if (checkResults())                                                   \
00196       {                                                                 \
00197         for (int i=0; i<nx; i++)                                        \
00198            {                                                            \
00199              f[i] = funcDefinition;                                     \
00200              df[i] = firstDerivDefinition;                              \
00201              TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i]), \
00202                                 std::runtime_error,                           \
00203                                 "Non-normal floating point result detected in " \
00204                                 "evaluation of unary functor "          \
00205                                 << name() << " at argument " << x[i]);  \
00206            }                                                            \
00207       }                                                                 \
00208     else                                                                \
00209       {                                                                 \
00210         for (int i=0; i<nx; i++)                                        \
00211            {                                                            \
00212              f[i] = funcDefinition;                                     \
00213              df[i] = firstDerivDefinition;                              \
00214            }                                                            \
00215       }                                                                 \
00216 }                                                                       \
00217   inline void functorName::eval2(const double* const x,                 \
00218                                int nx,                                  \
00219                                double* f,                               \
00220                                double* df,                              \
00221                                double* d2f) const                       \
00222 {                                                                       \
00223   if (checkResults())                                                   \
00224       {                                                                 \
00225         for (int i=0; i<nx; i++)                                        \
00226            {                                                            \
00227              f[i] = funcDefinition;                                     \
00228               df[i] = firstDerivDefinition;                             \
00229               d2f[i] = secondDerivDefinition;                           \
00230               TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i])||Teuchos::ScalarTraits<double>::isnaninf(d2f[i]), \
00231                                  std::runtime_error,                          \
00232                                  "Non-normal floating point result detected in " \
00233                                  "evaluation of unary functor "         \
00234                                  << name() << " at argument " << x[i] ); \
00235            }                                                            \
00236       }                                                                 \
00237     else                                                                \
00238       {                                                                 \
00239         for (int i=0; i<nx; i++)                                        \
00240            {                                                            \
00241              f[i] = funcDefinition;                                     \
00242                df[i] = firstDerivDefinition;                            \
00243                d2f[i] = secondDerivDefinition;                          \
00244            }                                                            \
00245       }                                                                 \
00246 }
00247 
00248 
00249 
00250 /** */
00251 #define SUNDANCE_UNARY_FUNCTOR3(opName, functorName, description, domain, \
00252                                funcDefinition, firstDerivDefinition,    \
00253                                 secondDerivDefinition, thirdDerivDefinition) \
00254   class functorName : public Sundance::UnaryFunctor                \
00255   {                                                                     \
00256   public:                                                               \
00257     /** ctor for description functor */                                 \
00258     functorName() : Sundance::UnaryFunctor(#opName, rcp(new domain)) {;} \
00259       /** virtual dtor */                                               \
00260       virtual ~functorName(){;}                                         \
00261       /** Evaluate function at an array of values */                    \
00262       void eval0(const double* const x, int nx, double* f) const ;      \
00263       /** Evaluate function and first derivative at an array of values */ \
00264       void eval1(const double* const x,                                 \
00265                  int nx,                                                \
00266                  double* f,                                             \
00267                  double* df) const ;                                    \
00268       /** Evaluate function and first two derivatives at an array of values */ \
00269       void eval2(const double* const x,                                 \
00270                  int nx,                                                \
00271                  double* f,                                             \
00272                  double* df,                                            \
00273                  double* d2f_dxx) const ;                               \
00274       /** Evaluate function and first thress derivatives at an array of values */ \
00275       void eval3(const double* const x,                                 \
00276                  int nx,                                                \
00277                  double* f,                                             \
00278                  double* df,                                            \
00279                  double* d2f_dxx,                                       \
00280                  double* d3f_dxxx) const ;                                        \
00281   };                                                                    \
00282   inline void functorName::eval0(const double* const x, int nx, double* f) const \
00283   {                                                                     \
00284     if (checkResults())                                                 \
00285       {                                                                 \
00286         for (int i=0; i<nx; i++)                                        \
00287           {                                                             \
00288             f[i] = funcDefinition;                                      \
00289             TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i]), std::runtime_error, "Non-normal floating point result detected in evaluation of unary functor " << name() << " at argument " << x[i]); \
00290           }                                                             \
00291      }                                                                  \
00292    else                                                                 \
00293      {                                                                  \
00294        for (int i=0; i<nx; i++) f[i] = funcDefinition;                  \
00295      }                                                                  \
00296 }                                                                       \
00297   inline void functorName::eval1(const double* const x,                 \
00298                                int nx,                                  \
00299                                double* f,                               \
00300                                double* df) const                        \
00301 {                                                                       \
00302   if (checkResults())                                                   \
00303       {                                                                 \
00304         for (int i=0; i<nx; i++)                                        \
00305            {                                                            \
00306              f[i] = funcDefinition;                                     \
00307              df[i] = firstDerivDefinition;                              \
00308              TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i]), \
00309                                 std::runtime_error,                           \
00310                                 "Non-normal floating point result detected in " \
00311                                 "evaluation of unary functor "          \
00312                                 << name() << " at argument " << x[i]);  \
00313            }                                                            \
00314       }                                                                 \
00315     else                                                                \
00316       {                                                                 \
00317         for (int i=0; i<nx; i++)                                        \
00318            {                                                            \
00319              f[i] = funcDefinition;                                     \
00320              df[i] = firstDerivDefinition;                              \
00321            }                                                            \
00322       }                                                                 \
00323 }                                                                       \
00324   inline void functorName::eval2(const double* const x,                 \
00325                                int nx,                                  \
00326                                double* f,                               \
00327                                double* df,                              \
00328                                double* d2f) const                       \
00329 {                                                                       \
00330   if (checkResults())                                                   \
00331       {                                                                 \
00332         for (int i=0; i<nx; i++)                                        \
00333            {                                                            \
00334              f[i] = funcDefinition;                                     \
00335               df[i] = firstDerivDefinition;                             \
00336               d2f[i] = secondDerivDefinition;                           \
00337               TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i])||Teuchos::ScalarTraits<double>::isnaninf(d2f[i]), \
00338                                  std::runtime_error,                          \
00339                                  "Non-normal floating point result detected in " \
00340                                  "evaluation of unary functor "         \
00341                                  << name() << " at argument " << x[i] ); \
00342            }                                                            \
00343       }                                                                 \
00344     else                                                                \
00345       {                                                                 \
00346         for (int i=0; i<nx; i++)                                        \
00347            {                                                            \
00348              f[i] = funcDefinition;                                     \
00349                df[i] = firstDerivDefinition;                            \
00350                d2f[i] = secondDerivDefinition;                          \
00351            }                                                            \
00352       }                                                                 \
00353 }                                                                     \
00354   inline void functorName::eval3(const double* const x,                 \
00355                                  int nx,                                \
00356                                  double* f,                             \
00357                                  double* df,                            \
00358                                  double* d2f,                           \
00359                                  double* d3f) const                     \
00360 {                                                                       \
00361   if (checkResults())                                                   \
00362       {                                                                 \
00363         for (int i=0; i<nx; i++)                                        \
00364            {                                                            \
00365              f[i] = funcDefinition;                                     \
00366               df[i] = firstDerivDefinition;                             \
00367               d2f[i] = secondDerivDefinition;                           \
00368               d3f[i] = thirdDerivDefinition;                           \
00369               TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::ScalarTraits<double>::isnaninf(f[i])||Teuchos::ScalarTraits<double>::isnaninf(df[i])||Teuchos::ScalarTraits<double>::isnaninf(d2f[i])||Teuchos::ScalarTraits<double>::isnaninf(d3f[i]), \
00370                                  std::runtime_error,                          \
00371                                  "Non-normal floating point result detected in " \
00372                                  "evaluation of unary functor "         \
00373                                  << name() << " at argument " << x[i] ); \
00374            }                                                            \
00375       }                                                                 \
00376     else                                                                \
00377       {                                                                 \
00378         for (int i=0; i<nx; i++)                                        \
00379            {                                                            \
00380              f[i] = funcDefinition;                                     \
00381                df[i] = firstDerivDefinition;                            \
00382                d2f[i] = secondDerivDefinition;                          \
00383                d3f[i] = thirdDerivDefinition;                          \
00384            }                                                            \
00385       }                                                                 \
00386 }
00387 
00388                   
00389 #endif  /* DOXYGEN_DEVELOPER_ONLY */  
00390 
00391 #endif

Site Contact