Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Sacado_ELRCacheFad_SFad.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Sacado Package
4 //
5 // Copyright 2006 NTESS and the Sacado contributors.
6 // SPDX-License-Identifier: LGPL-2.1-or-later
7 //
8 // ***********************************************************************
9 //
10 // The forward-mode AD classes in Sacado are a derivative work of the
11 // expression template classes in the Fad package by Nicolas Di Cesare.
12 // The following banner is included in the original Fad source code:
13 //
14 // ************ DO NOT REMOVE THIS BANNER ****************
15 //
16 // Nicolas Di Cesare <Nicolas.Dicesare@ann.jussieu.fr>
17 // http://www.ann.jussieu.fr/~dicesare
18 //
19 // CEMRACS 98 : C++ courses,
20 // templates : new C++ techniques
21 // for scientific computing
22 //
23 //********************************************************
24 //
25 // A short implementation ( not all operators and
26 // functions are overloaded ) of 1st order Automatic
27 // Differentiation in forward mode (FAD) using
28 // EXPRESSION TEMPLATES.
29 //
30 //********************************************************
31 // @HEADER
32 
33 #ifndef SACADO_ELRCACHEFAD_SFAD_HPP
34 #define SACADO_ELRCACHEFAD_SFAD_HPP
35 
39 #include "Sacado_mpl_range_c.hpp"
40 #include "Sacado_mpl_for_each.hpp"
41 
42 namespace Sacado {
43 
44  namespace ELRCacheFad {
45 
47  template <typename T, int Num>
48  struct SFadExprTag {};
49 
50  // Forward declaration
51  template <typename T, int Num> class SFad;
52 
60  template <typename T, int Num>
61  class Expr< SFadExprTag<T,Num> > {
62 
63  public:
64 
66  typedef typename RemoveConst<T>::type value_type;
67 
70 
73 
75  static const int num_args = 1;
76 
78  static const bool is_linear = true;
79 
84 
87  Expr() : val_( T(0.)) { ss_array<T>::zero(dx_, Num); }
88 
90 
93  template <typename S>
96  val_(x) {
97  ss_array<T>::zero(dx_, Num);
98  }
99 
101 
105  Expr(const int sz, const T & x, const DerivInit zero_out = InitDerivArray) : val_(x) {
106 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
107  if (sz != Num)
108  throw "ELRCacheFad::SFad() Error: Supplied derivative dimension does not match compile time length.";
109 #endif
110 
111  if (zero_out == InitDerivArray)
112  ss_array<T>::zero(dx_, Num);
113  }
114 
116 
122  Expr(const int sz, const int i, const T & x) :
123  val_(x) {
124 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
125  if (sz != Num)
126  throw "ELRCacheFad::SFad() Error: Supplied derivative dimension does not match compile time length.";
127  if (i >= Num)
128  throw "ELRCacheFad::SFad() Error: Invalid derivative index.";
129 #endif
130 
131  ss_array<T>::zero(dx_, Num);
132  dx_[i]=1.;
133  }
134 
137  Expr(const Expr& x) : val_(x.val_) {
138  //ss_array<T>::copy(x.dx_, dx_, Num);
139  for (int i=0; i<Num; i++)
140  dx_[i] = x.dx_[i];
141  }
142 
144  template <typename S>
147 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
148  if (x.size() != Num)
149  throw "ELRCacheFad::SFad() Error: Attempt to assign with incompatible sizes";
150 #endif
151 
152  x.cache();
153 
154  this->val() = x.val();
155 
156  // Compute partials
157  LocalAccumOp< Expr<S> > op(x);
158 
159  // Compute each tangent direction
160  for(int i=0; i<Num; ++i) {
161  op.t = T(0.);
162  op.i = i;
163 
164  // Automatically unrolled loop that computes
165  // for (int j=0; j<N; j++)
166  // op.t += op.partials[j] * x.getTangent<j>(i);
168 
169  dx_[i] = op.t;
170 
171  }
172  }
173 
176  ~Expr() {}
177 
179 
186  void diff(const int ith, const int n) {
187 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
188  if (n != Num)
189  throw "ELRCacheFad::diff() Error: Supplied derivative dimension does not match compile time length.";
190 #endif
191 
192  ss_array<T>::zero(dx_, Num);
193  dx_[ith] = T(1.);
194  }
195 
197 
202  void resize(int sz) {
203 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
204  if (sz != Num)
205  throw "ELRCacheFad::resize() Error: Cannot resize fixed derivative array dimension";
206 #endif
207  }
208 
210 
215  void expand(int sz) { resize(sz); }
216 
219  void zero() { ss_array<T>::zero(dx_, Num); }
220 
223  void setUpdateValue(bool update_val) { }
224 
227  bool updateValue() const { return true; }
228 
231  void cache() const {}
232 
234  template <typename S>
236  SACADO_ENABLE_EXPR_FUNC(bool) isEqualTo(const Expr<S>& x) const {
237  typedef IsEqual<value_type> IE;
238  if (x.size() != this->size()) return false;
239  bool eq = IE::eval(x.val(), this->val());
240  for (int i=0; i<this->size(); i++)
241  eq = eq && IE::eval(x.dx(i), this->dx(i));
242  return eq;
243  }
244 
246 
251 
254  const T& val() const { return val_;}
255 
258  T& val() { return val_;}
259 
261 
266 
269  int size() const { return Num;}
270 
276  int availableSize() const { return Num; }
277 
280  bool hasFastAccess() const { return true; }
281 
284  bool isPassive() const { return false; }
285 
288  void setIsConstant(bool is_const) {}
289 
292  const T* dx() const { return &(dx_[0]);}
293 
296  const T& dx(int i) const { return dx_[i]; }
297 
300  T& fastAccessDx(int i) { return dx_[i];}
301 
304  const T& fastAccessDx(int i) const { return dx_[i];}
305 
308  void computePartials(const T& bar, value_type partials[]) const {
309  partials[0] = bar;
310  }
311 
314  void getTangents(int i, value_type dots[]) const {
315  dots[0] = this->dx_[i];
316  }
317 
319  template <int Arg>
321  bool isActive() const { return true; }
322 
324  template <int Arg>
326  T getTangent(int i) const { return this->dx_[i]; }
327 
330  const value_type* getDx(int j) const { return this->dx(); }
331 
333 
338 
340  template <typename S>
342  SACADO_ENABLE_VALUE_FUNC(Expr&) operator=(const S& v) {
343  val_ = v;
344  ss_array<T>::zero(dx_, Num);
345  return *this;
346  }
347 
350  Expr& operator=(const Expr& x) {
351  if (this != &x) {
352  // Copy value
353  val_ = x.val_;
354 
355  // Copy dx_
356  //ss_array<T>::copy(x.dx_, dx_, Num);
357  for (int i=0; i<Num; i++)
358  dx_[i] = x.dx_[i];
359  }
360  return *this;
361  }
362 
364  template <typename S>
366  SACADO_ENABLE_EXPR_FUNC(Expr&) operator=(const Expr<S>& x) {
367 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
368  if (x.size() != Num)
369  throw "ELRCacheFad::operator=() Error: Attempt to assign with incompatible sizes";
370 #endif
371 
372  x.cache();
373 
374  // Compute partials
375  LocalAccumOp< Expr<S> > op(x);
376 
377  // Compute each tangent direction
378  for(int i=0; i<Num; ++i) {
379  op.t = T(0.);
380  op.i = i;
381 
382  // Automatically unrolled loop that computes
383  // for (int j=0; j<N; j++)
384  // op.t += op.partials[j] * x.getTangent<j>(i);
386 
387  dx_[i] = op.t;
388  }
389 
390  this->val() = x.val();
391 
392  return *this;
393  }
394 
396 
401 
403  template <typename S>
405  SACADO_ENABLE_VALUE_FUNC(Expr&) operator += (const S& v) {
406  this->val() += v;
407  return *this;
408  }
409 
411  template <typename S>
413  SACADO_ENABLE_VALUE_FUNC(Expr&) operator -= (const S& v) {
414  this->val() -= v;
415  return *this;
416  }
417 
419  template <typename S>
421  SACADO_ENABLE_VALUE_FUNC(Expr&) operator *= (const S& v) {
422  this->val() *= v;
423  for (int i=0; i<Num; ++i)
424  dx_[i] *= v;
425  return *this;
426  }
427 
429  template <typename S>
431  SACADO_ENABLE_VALUE_FUNC(Expr&) operator /= (const S& v) {
432  this->val() /= v;
433  for (int i=0; i<Num; ++i)
434  dx_[i] /= v;
435  return *this;
436  }
437 
439  template <typename S>
441  SACADO_ENABLE_EXPR_FUNC(Expr&) operator += (const Expr<S>& x) {
442 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
443  if (x.size() != Num)
444  throw "ELRCacheFad::operator+=() Error: Attempt to assign with incompatible sizes";
445 #endif
446 
447  x.cache();
448 
449  // Compute partials
450  LocalAccumOp< Expr<S> > op(x);
451 
452  // Compute each tangent direction
453  for(int i=0; i<Num; ++i) {
454  op.t = T(0.);
455  op.i = i;
456 
457  // Automatically unrolled loop that computes
458  // for (int j=0; j<N; j++)
459  // op.t += op.partials[j] * x.getTangent<j>(i);
461 
462  dx_[i] += op.t;
463  }
464 
465  this->val() += x.val();
466 
467  return *this;
468  }
469 
471  template <typename S>
473  SACADO_ENABLE_EXPR_FUNC(Expr&) operator -= (const Expr<S>& x) {
474 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
475  if (x.size() != Num)
476  throw "ELRCacheFad::operator-=() Error: Attempt to assign with incompatible sizes";
477 #endif
478 
479  x.cache();
480 
481  // Compute partials
482  LocalAccumOp< Expr<S> > op(x);
483 
484  // Compute each tangent direction
485  for(int i=0; i<Num; ++i) {
486  op.t = T(0.);
487  op.i = i;
488 
489  // Automatically unrolled loop that computes
490  // for (int j=0; j<N; j++)
491  // op.t += op.partials[j] * x.getTangent<j>(i);
493 
494  dx_[i] -= op.t;
495  }
496 
497  this->val() -= x.val();
498 
499  return *this;
500  }
501 
503  template <typename S>
505  SACADO_ENABLE_EXPR_FUNC(Expr&) operator *= (const Expr<S>& x) {
506  x.cache();
507 
508  T xval = x.val();
509 
510 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
511  if (x.size() != Num)
512  throw "ELRCacheFad::operator*=() Error: Attempt to assign with incompatible sizes";
513 #endif
514 
515  // Compute partials
516  LocalAccumOp< Expr<S> > op(x);
517 
518  // Compute each tangent direction
519  for(int i=0; i<Num; ++i) {
520  op.t = T(0.);
521  op.i = i;
522 
523  // Automatically unrolled loop that computes
524  // for (int j=0; j<N; j++)
525  // op.t += op.partials[j] * x.getTangent<j>(i);
527 
528  dx_[i] = val_ * op.t + dx_[i] * xval;
529  }
530 
531  // Compute value
532  val_ *= xval;
533 
534  return *this;
535  }
536 
538  template <typename S>
540  SACADO_ENABLE_EXPR_FUNC(Expr&) operator /= (const Expr<S>& x) {
541  x.cache();
542 
543  T xval = x.val();
544 
545 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
546  if (x.size() != Num)
547  throw "ELRCacheFad::operator/=() Error: Attempt to assign with incompatible sizes";
548 #endif
549 
550  // Compute partials
551  LocalAccumOp< Expr<S> > op(x);
552 
553  T xval2 = xval*xval;
554 
555  // Compute each tangent direction
556  for(int i=0; i<Num; ++i) {
557  op.t = T(0.);
558  op.i = i;
559 
560  // Automatically unrolled loop that computes
561  // for (int j=0; j<N; j++)
562  // op.t += op.partials[j] * x.getTangent<j>(i);
564 
565  dx_[i] = (dx_[i] * xval - val_ * op.t) / xval2;
566  }
567 
568  // Compute value
569  val_ /= xval;
570 
571  return *this;
572  }
573 
575 
576  protected:
577 
579  T dx_[Num];
580 
583 
584  // Functor for mpl::for_each to compute the local accumulation
585  // of a tangent derivative
586  //
587  // We use getTangent<>() to get dx components from expression
588  // arguments instead of getting the argument directly or extracting
589  // the dx array due to striding in ViewFad (or could use striding
590  // directly here if we need to get dx array).
591  template <typename ExprT>
592  struct LocalAccumOp {
593  typedef typename ExprT::value_type value_type;
594  static const int N = ExprT::num_args;
595  const ExprT& x;
596  mutable value_type t;
597  value_type partials[N];
598  int i;
600  LocalAccumOp(const ExprT& x_) : x(x_) {
601  x.computePartials(value_type(1.), partials);
602  }
603  template <typename ArgT>
605  void operator () (ArgT arg) const {
606  const int Arg = ArgT::value;
607  if (x.template isActive<Arg>())
608  t += partials[Arg] * x.template getTangent<Arg>(i);
609  }
610  };
611 
612  }; // class Expr<SFadExprTag>
613 
614  } // namespace ELRCacheFad
615 
616 } // namespace Sacado
617 
618 #define FAD_NS ELRCacheFad
619 #include "Sacado_Fad_SFad_tmpl.hpp"
620 #undef FAD_NS
621 
624 
625 #endif // SACADO_ELRCACHEFAD_SFAD_HPP
SACADO_INLINE_FUNCTION Expr(const int sz, const T &x, const DerivInit zero_out=InitDerivArray)
Constructor with size sz and value x.
void f()
SACADO_INLINE_FUNCTION Expr(const Expr< S > &x, SACADO_ENABLE_EXPR_CTOR_DECL)
Copy constructor from any Expression object.
SACADO_INLINE_FUNCTION const value_type * getDx(int j) const
Get dx array.
ScalarType< value_type >::type scalar_type
Typename of scalar&#39;s (which may be different from T)
SACADO_INLINE_FUNCTION void cache() const
Cache values.
SACADO_INLINE_FUNCTION const T & fastAccessDx(int i) const
Returns derivative component i without bounds checking.
expr expr dx(i)
#define SACADO_ENABLE_VALUE_CTOR_DECL
SACADO_INLINE_FUNCTION SACADO_ENABLE_EXPR_FUNC(bool) isEqualTo(const Expr< S > &x) const
Returns whether two Fad objects have the same values.
SACADO_INLINE_FUNCTION bool hasFastAccess() const
Returns true if derivative array is not empty.
SFad< value_type, Num > base_expr_type
Typename of base-expressions.
SACADO_INLINE_FUNCTION Expr()
Default constructor.
expr bar
SACADO_INLINE_FUNCTION void computePartials(const T &bar, value_type partials[]) const
Return partials w.r.t. arguments.
#define SACADO_ENABLE_EXPR_CTOR_DECL
SACADO_INLINE_FUNCTION void setIsConstant(bool is_const)
Set whether variable is constant.
SACADO_INLINE_FUNCTION void expand(int sz)
Expand derivative array to size sz.
SACADO_INLINE_FUNCTION T & val()
Returns value.
SACADO_INLINE_FUNCTION void resize(int sz)
Resize derivative array to length sz.
SACADO_INLINE_FUNCTION Expr(const int sz, const int i, const T &x)
Constructor with size sz, index i, and value x.
SACADO_INLINE_FUNCTION Expr(const Expr &x)
Copy constructor.
expr val()
#define T
Definition: Sacado_rad.hpp:553
SACADO_INLINE_FUNCTION void zero()
Zero out the derivative array.
SACADO_INLINE_FUNCTION void diff(const int ith, const int n)
Set Fad object as the ith independent variable.
#define SACADO_ENABLE_VALUE_FUNC(RETURN_TYPE)
Base template specification for testing equivalence.
SACADO_INLINE_FUNCTION const T & val() const
Returns value.
static double x_
Wrapper for a generic expression template.
SACADO_INLINE_FUNCTION int size() const
Returns number of derivative components.
RemoveConst< T >::type value_type
Typename of values.
SACADO_INLINE_FUNCTION Expr(const S &x, SACADO_ENABLE_VALUE_CTOR_DECL)
Constructor with supplied value x.
const int N
SACADO_INLINE_FUNCTION bool isActive() const
Return whether argument is active.
#define SACADO_ENABLE_EXPR_FUNC(RETURN_TYPE)
SACADO_INLINE_FUNCTION const T & dx(int i) const
Returns derivative component i with bounds checking.
DerivInit
Enum use to signal whether the derivative array should be initialized in AD object constructors...
int value
SACADO_INLINE_FUNCTION int availableSize() const
Returns number of derivative components that can be stored without reallocation.
SACADO_INLINE_FUNCTION bool updateValue() const
Return whether this Fad object has an updated value.
SACADO_INLINE_FUNCTION bool isPassive() const
Returns true if derivative array is empty.
static SACADO_INLINE_FUNCTION void zero(T *dest, int sz)
Zero out array dest of length sz.
Initialize the derivative array.
SACADO_INLINE_FUNCTION T & fastAccessDx(int i)
Returns derivative component i without bounds checking.
SACADO_INLINE_FUNCTION void setUpdateValue(bool update_val)
Set whether this Fad object should update values.
#define SACADO_INLINE_FUNCTION
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
Return tangent component i of arguments.
SACADO_INLINE_FUNCTION const T * dx() const
Returns derivative array.
SACADO_INLINE_FUNCTION T getTangent(int i) const
Return tangent component i of argument Arg.
A tag for specializing Expr for SFad expressions.