Sacado_ELRFad_GeneralFadImp.hpp

Go to the documentation of this file.
00001 // $Id: Sacado_ELRFad_GeneralFadImp.hpp,v 1.1 2007/08/13 21:25:19 etphipp Exp $ 
00002 // $Source: /space/CVS/Trilinos/packages/sacado/src/Sacado_ELRFad_GeneralFadImp.hpp,v $ 
00003 // @HEADER
00004 // ***********************************************************************
00005 // 
00006 //                           Sacado Package
00007 //                 Copyright (2006) Sandia Corporation
00008 // 
00009 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00010 // the U.S. Government retains certain rights in this software.
00011 // 
00012 // This library is free software; you can redistribute it and/or modify
00013 // it under the terms of the GNU Lesser General Public License as
00014 // published by the Free Software Foundation; either version 2.1 of the
00015 // License, or (at your option) any later version.
00016 //  
00017 // This library is distributed in the hope that it will be useful, but
00018 // WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Lesser General Public License for more details.
00021 //  
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00025 // USA
00026 // Questions? Contact David M. Gay (dmgay@sandia.gov) or Eric T. Phipps
00027 // (etphipp@sandia.gov).
00028 // 
00029 // ***********************************************************************
00030 //
00031 // The forward-mode AD classes in Sacado are a derivative work of the
00032 // expression template classes in the Fad package by Nicolas Di Cesare.  
00033 // The following banner is included in the original Fad source code:
00034 //
00035 // ************ DO NOT REMOVE THIS BANNER ****************
00036 //
00037 //  Nicolas Di Cesare <Nicolas.Dicesare@ann.jussieu.fr>
00038 //  http://www.ann.jussieu.fr/~dicesare
00039 //
00040 //            CEMRACS 98 : C++ courses, 
00041 //         templates : new C++ techniques 
00042 //            for scientific computing 
00043 // 
00044 //********************************************************
00045 //
00046 //  A short implementation ( not all operators and 
00047 //  functions are overloaded ) of 1st order Automatic
00048 //  Differentiation in forward mode (FAD) using
00049 //  EXPRESSION TEMPLATES.
00050 //
00051 //********************************************************
00052 // @HEADER
00053 
00054 #include "Sacado_ConfigDefs.h"
00055 #include "Sacado_mpl_range_c.hpp"
00056 #include "Sacado_mpl_for_each.hpp"
00057 
00058 // template <typename T, typename Storage> 
00059 // template <typename S> 
00060 // inline Sacado::ELRFad::GeneralFad<T,Storage>::GeneralFad(const Expr<S>& x) :
00061 //   s_(T(0.))
00062 // {
00063 //   int sz = x.size();
00064 
00065 //   if (sz != s_.size()) 
00066 //     s_.resize(sz);
00067 
00068 //   if (sz) {
00069 
00070 //     // Number of arguments
00071 //     const int N = Expr<S>::num_args;
00072 
00073 //     // Array to store partials
00074 //     T partials[N];
00075 
00076 //     // Array to store tangents
00077 //     T dots[N];
00078 
00079 //     // Compute partials
00080 //     x.computePartials(T(1.), partials);
00081   
00082 //     // Compute each tangent direction
00083 //     for(int i=0; i<sz; ++i) {
00084 //       T t = T(0.);
00085 //       x.getTangents(i,dots);
00086 //       for (int j=0; j<N; j++) {
00087 //  t += partials[j]*dots[j];
00088 //       }
00089 //       s_.dx_[i] = t;
00090 //     }
00091 
00092 //   }
00093   
00094 //   // Compute value
00095 //   s_.val_ = x.val();
00096 // }
00097 
00098 template <typename T, typename Storage> 
00099 template <typename S> 
00100 inline Sacado::ELRFad::GeneralFad<T,Storage>::GeneralFad(const Expr<S>& x) :
00101   s_(T(0.))
00102 {
00103   int sz = x.size();
00104 
00105   if (sz != s_.size()) 
00106     s_.resize(sz);
00107 
00108   if (sz) {
00109 
00110     // Number of arguments
00111     const int N = Expr<S>::num_args;
00112 
00113     // Compute partials
00114     LocalAccumOp< Expr<S> > op(x);
00115   
00116     // Compute each tangent direction
00117     for(int i=0; i<sz; ++i) {
00118       op.t = T(0.);
00119       op.i = i;
00120 
00121       // Automatically unrolled loop that computes
00122       // for (int j=0; j<N; j++)
00123       //   op.t += op.partials[j] * x.getTangent<j>(i);
00124       Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00125 
00126       s_.dx_[i] = op.t;
00127     }
00128 
00129   }
00130   
00131   // Compute value
00132   s_.val_ = x.val();
00133 }
00134 
00135 template <typename T, typename Storage> 
00136 inline void 
00137 Sacado::ELRFad::GeneralFad<T,Storage>::diff(const int ith, const int n) 
00138 { 
00139   if (s_.size() == 0) 
00140     s_.resize(n);
00141 
00142   s_.zero();
00143   s_.dx_[ith] = T(1.);
00144 
00145 }
00146 
00147 template <typename T, typename Storage> 
00148 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00149 Sacado::ELRFad::GeneralFad<T,Storage>::operator=(const T& val) 
00150 {
00151   s_.val_ = val;
00152 
00153   if (s_.size()) {
00154     s_.zero();    // We need to zero out the array for future resizes
00155     s_.resize(0);
00156   }
00157 
00158   return *this;
00159 }
00160 
00161 template <typename T, typename Storage> 
00162 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00163 Sacado::ELRFad::GeneralFad<T,Storage>::operator=(
00164              const Sacado::ELRFad::GeneralFad<T,Storage>& x) 
00165 {
00166   // Copy value & dx_
00167   s_.operator=(x.s_);
00168   
00169   return *this;
00170 }
00171 
00172 template <typename T, typename Storage> 
00173 template <typename S> 
00174 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00175 Sacado::ELRFad::GeneralFad<T,Storage>::operator=(const Expr<S>& x) 
00176 {
00177   int sz = x.size();
00178 
00179   if (sz != s_.size()) 
00180     s_.resize(sz);
00181 
00182   if (sz) {
00183 
00184     // Number of arguments
00185     const int N = Expr<S>::num_args;
00186 
00187     // Compute partials
00188     LocalAccumOp< Expr<S> > op(x);
00189   
00190     // Compute each tangent direction
00191     for(int i=0; i<sz; ++i) {
00192       op.t = T(0.);
00193       op.i = i;
00194 
00195       // Automatically unrolled loop that computes
00196       // for (int j=0; j<N; j++)
00197       //   op.t += op.partials[j] * x.getTangent<j>(i);
00198       Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00199 
00200       s_.dx_[i] = op.t;
00201     }
00202 
00203   }
00204   
00205   // Compute value
00206   s_.val_ = x.val();
00207   
00208   return *this;
00209 }
00210 
00211 template <typename T, typename Storage> 
00212 inline  Sacado::ELRFad::GeneralFad<T,Storage>& 
00213 Sacado::ELRFad::GeneralFad<T,Storage>::operator += (const T& val)
00214 {
00215   s_.val_ += val;
00216 
00217   return *this;
00218 }
00219 
00220 template <typename T, typename Storage> 
00221 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00222 Sacado::ELRFad::GeneralFad<T,Storage>::operator -= (const T& val)
00223 {
00224   s_.val_ -= val;
00225 
00226   return *this;
00227 }
00228 
00229 template <typename T, typename Storage> 
00230 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00231 Sacado::ELRFad::GeneralFad<T,Storage>::operator *= (const T& val)
00232 {
00233   int sz = s_.size();
00234 
00235   s_.val_ *= val;
00236   for (int i=0; i<sz; ++i)
00237     s_.dx_[i] *= val;
00238 
00239   return *this;
00240 }
00241 
00242 template <typename T, typename Storage> 
00243 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00244 Sacado::ELRFad::GeneralFad<T,Storage>::operator /= (const T& val)
00245 {
00246   int sz = s_.size();
00247 
00248   s_.val_ /= val;
00249   for (int i=0; i<sz; ++i)
00250     s_.dx_[i] /= val;
00251 
00252   return *this;
00253 }
00254 
00255 template <typename T, typename Storage> 
00256 template <typename S> 
00257 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00258 Sacado::ELRFad::GeneralFad<T,Storage>::operator += (
00259                const Sacado::ELRFad::Expr<S>& x)
00260 {
00261   int xsz = x.size(), sz = s_.size();
00262 
00263 #ifdef SACADO_DEBUG
00264   if ((xsz != sz) && (xsz != 0) && (sz != 0))
00265     throw "Fad Error:  Attempt to assign with incompatible sizes";
00266 #endif
00267 
00268   // Number of arguments
00269   const int N = Expr<S>::num_args;
00270 
00271   if (xsz) {
00272 
00273     // Compute partials
00274     LocalAccumOp< Expr<S> > op(x);
00275 
00276     if (sz) {
00277 
00278       // Compute each tangent direction
00279       for(int i=0; i<xsz; ++i) {
00280   op.t = T(0.);
00281   op.i = i;
00282   
00283   // Automatically unrolled loop that computes
00284   // for (int j=0; j<N; j++)
00285   //   op.t += op.partials[j] * x.getTangent<j>(i);
00286   Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00287   
00288   s_.dx_[i] += op.t;
00289       }
00290 
00291     }
00292 
00293     else {
00294 
00295       s_.resize(xsz);
00296 
00297       // Compute each tangent direction
00298       for(int i=0; i<xsz; ++i) {
00299   op.t = T(0.);
00300   op.i = i;
00301   
00302   // Automatically unrolled loop that computes
00303   // for (int j=0; j<N; j++)
00304   //   op.t += op.partials[j] * x.getTangent<j>(i);
00305   Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00306   
00307   s_.dx_[i] = op.t;
00308       }
00309 
00310     }
00311 
00312   }
00313   
00314   // Compute value
00315   s_.val_ += x.val();
00316 
00317   return *this;
00318 }
00319 
00320 template <typename T, typename Storage> 
00321 template <typename S> 
00322 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00323 Sacado::ELRFad::GeneralFad<T,Storage>::operator -= (
00324                 const Sacado::ELRFad::Expr<S>& x)
00325 {
00326   int xsz = x.size(), sz = s_.size();
00327 
00328 #ifdef SACADO_DEBUG
00329   if ((xsz != sz) && (xsz != 0) && (sz != 0))
00330     throw "Fad Error:  Attempt to assign with incompatible sizes";
00331 #endif
00332 
00333   // Number of arguments
00334   const int N = Expr<S>::num_args;
00335 
00336   if (xsz) {
00337 
00338     // Compute partials
00339     LocalAccumOp< Expr<S> > op(x);
00340 
00341     if (sz) {
00342 
00343       // Compute each tangent direction
00344       for(int i=0; i<xsz; ++i) {
00345   op.t = T(0.);
00346   op.i = i;
00347   
00348   // Automatically unrolled loop that computes
00349   // for (int j=0; j<N; j++)
00350   //   op.t += op.partials[j] * x.getTangent<j>(i);
00351   Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00352   
00353   s_.dx_[i] -= op.t;
00354       }
00355 
00356     }
00357 
00358     else {
00359 
00360       s_.resize(xsz);
00361 
00362       // Compute each tangent direction
00363       for(int i=0; i<xsz; ++i) {
00364   op.t = T(0.);
00365   op.i = i;
00366   
00367   // Automatically unrolled loop that computes
00368   // for (int j=0; j<N; j++)
00369   //   op.t += op.partials[j] * x.getTangent<j>(i);
00370   Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00371   
00372   s_.dx_[i] = -op.t;
00373       }
00374 
00375     }
00376 
00377   }
00378 
00379   s_.val_ -= x.val();
00380 
00381   return *this;
00382 }
00383 
00384 template <typename T, typename Storage> 
00385 template <typename S> 
00386 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00387 Sacado::ELRFad::GeneralFad<T,Storage>::operator *= (
00388                const Sacado::ELRFad::Expr<S>& x)
00389 {
00390   int xsz = x.size(), sz = s_.size();
00391   T xval = x.val();
00392 
00393 #ifdef SACADO_DEBUG
00394   if ((xsz != sz) && (xsz != 0) && (sz != 0))
00395     throw "Fad Error:  Attempt to assign with incompatible sizes";
00396 #endif
00397 
00398   // Number of arguments
00399   const int N = Expr<S>::num_args;
00400 
00401   if (xsz) {
00402 
00403     // Compute partials
00404     LocalAccumOp< Expr<S> > op(x);
00405 
00406     if (sz) {
00407 
00408       // Compute each tangent direction
00409       for(int i=0; i<xsz; ++i) {
00410   op.t = T(0.);
00411   op.i = i;
00412   
00413   // Automatically unrolled loop that computes
00414   // for (int j=0; j<N; j++)
00415   //   op.t += op.partials[j] * x.getTangent<j>(i);
00416   Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00417   
00418   s_.dx_[i] = s_.val_ * op.t + s_.dx_[i] * xval;
00419       }
00420 
00421     }
00422 
00423     else {
00424 
00425       s_.resize(xsz);
00426 
00427       // Compute each tangent direction
00428       for(int i=0; i<xsz; ++i) {
00429   op.t = T(0.);
00430   op.i = i;
00431   
00432   // Automatically unrolled loop that computes
00433   // for (int j=0; j<N; j++)
00434   //   op.t += op.partials[j] * x.getTangent<j>(i);
00435   Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00436   
00437   s_.dx_[i] = s_.val_ * op.t;
00438       }
00439 
00440     }
00441 
00442   }
00443 
00444   else {
00445 
00446     if (sz) {
00447       for (int i=0; i<sz; ++i)
00448   s_.dx_[i] *= xval;
00449     }
00450 
00451   }
00452 
00453   s_.val_ *= xval;
00454 
00455   return *this;
00456 }
00457 
00458 template <typename T, typename Storage>
00459 template <typename S> 
00460 inline Sacado::ELRFad::GeneralFad<T,Storage>& 
00461 Sacado::ELRFad::GeneralFad<T,Storage>::operator /= (
00462                const Sacado::ELRFad::Expr<S>& x)
00463 {
00464   int xsz = x.size(), sz = s_.size();
00465   T xval = x.val();
00466 
00467 #ifdef SACADO_DEBUG
00468   if ((xsz != sz) && (xsz != 0) && (sz != 0))
00469     throw "Fad Error:  Attempt to assign with incompatible sizes";
00470 #endif
00471 
00472   // Number of arguments
00473   const int N = Expr<S>::num_args;
00474 
00475   if (xsz) {
00476 
00477     // Compute partials
00478     LocalAccumOp< Expr<S> > op(x);
00479 
00480     T xval2 = xval*xval;
00481 
00482     if (sz) {
00483 
00484       // Compute each tangent direction
00485       for(int i=0; i<xsz; ++i) {
00486   op.t = T(0.);
00487   op.i = i;
00488   
00489   // Automatically unrolled loop that computes
00490   // for (int j=0; j<N; j++)
00491   //   op.t += op.partials[j] * x.getTangent<j>(i);
00492   Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00493   
00494   s_.dx_[i] = (s_.dx_[i] * xval - s_.val_ * op.t) / xval2;
00495       }
00496 
00497     }
00498 
00499     else {
00500 
00501       s_.resize(xsz);
00502 
00503       // Compute each tangent direction
00504       for(int i=0; i<xsz; ++i) {
00505   op.t = T(0.);
00506   op.i = i;
00507   
00508   // Automatically unrolled loop that computes
00509   // for (int j=0; j<N; j++)
00510   //   op.t += op.partials[j] * x.getTangent<j>(i);
00511   Sacado::mpl::for_each< mpl::range_c< int, 0, N > > f(op);
00512   
00513   s_.dx_[i] = -s_.val_ * op.t / xval2;
00514       }
00515 
00516     }
00517 
00518   }
00519 
00520   else {
00521 
00522     if (sz) {
00523       for (int i=0; i<sz; ++i)
00524   s_.dx_[i] /= xval;
00525     }
00526 
00527   }
00528 
00529   s_.val_ /= xval;
00530 
00531   return *this;
00532 }
00533 

Generated on Wed May 12 21:59:04 2010 for Sacado Package Browser (Single Doxygen Collection) by  doxygen 1.4.7