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