Sacado Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Sacado_ELRFad_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_ELRFAD_SFAD_HPP
34 #define SACADO_ELRFAD_SFAD_HPP
35 
39 #include "Sacado_mpl_range_c.hpp"
40 #include "Sacado_mpl_for_each.hpp"
41 
42 namespace Sacado {
43 
44  namespace ELRFad {
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 "SELRFad::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 "SELRFad::SFad() Error: Supplied derivative dimension does not match compile time length.";
127  if (i >= Num)
128  throw "SELRFad::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 "SELRFad::SFad() Error: Attempt to assign with incompatible sizes";
150 #endif
151 
152  // Compute partials
153  LocalAccumOp< Expr<S> > op(x);
154 
155  // Compute each tangent direction
156  for(int i=0; i<Num; ++i) {
157  op.t = T(0.);
158  op.i = i;
159 
160  // Automatically unrolled loop that computes
161  // for (int j=0; j<N; j++)
162  // op.t += op.partials[j] * x.getTangent<j>(i);
164 
165  dx_[i] = op.t;
166 
167  }
168 
169  this->val() = x.val();
170  }
171 
174  ~Expr() {}
175 
177 
184  void diff(const int ith, const int n) {
185 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
186  if (n != Num)
187  throw "SELRFad::diff() Error: Supplied derivative dimension does not match compile time length.";
188 #endif
189 
190  ss_array<T>::zero(dx_, Num);
191  dx_[ith] = T(1.);
192  }
193 
195 
200  void resize(int sz) {
201 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
202  if (sz != Num)
203  throw "SELRFad::resize() Error: Cannot resize fixed derivative array dimension";
204 #endif
205  }
206 
208 
213  void expand(int sz) { resize(sz); }
214 
217  void zero() { ss_array<T>::zero(dx_, Num); }
218 
221  void setUpdateValue(bool update_val) { }
222 
225  bool updateValue() const { return true; }
226 
229  void cache() const {}
230 
232  template <typename S>
234  SACADO_ENABLE_EXPR_FUNC(bool) isEqualTo(const Expr<S>& x) const {
235  typedef IsEqual<value_type> IE;
236  if (x.size() != this->size()) return false;
237  bool eq = IE::eval(x.val(), this->val());
238  for (int i=0; i<this->size(); i++)
239  eq = eq && IE::eval(x.dx(i), this->dx(i));
240  return eq;
241  }
242 
244 
249 
252  const T& val() const { return val_;}
253 
256  T& val() { return val_;}
257 
259 
264 
267  int size() const { return Num;}
268 
274  int availableSize() const { return Num; }
275 
278  bool hasFastAccess() const { return true; }
279 
282  bool isPassive() const { return false; }
283 
286  void setIsConstant(bool is_const) {}
287 
290  const T* dx() const { return &(dx_[0]);}
291 
294  const T& dx(int i) const { return dx_[i]; }
295 
298  T& fastAccessDx(int i) { return dx_[i];}
299 
302  const T& fastAccessDx(int i) const { return dx_[i];}
303 
306  void computePartials(const T& bar, value_type partials[]) const {
307  partials[0] = bar;
308  }
309 
312  void getTangents(int i, value_type dots[]) const {
313  dots[0] = this->dx_[i];
314  }
315 
317  template <int Arg>
319  bool isActive() const { return true; }
320 
322  template <int Arg>
324  const T& getTangent(int i) const { return this->dx_[i]; }
325 
328  const value_type* getDx(int j) const { return this->dx(); }
329 
331 
336 
338  template <typename S>
340  SACADO_ENABLE_VALUE_FUNC(Expr&) operator=(const S& v) {
341  val_ = v;
342  ss_array<T>::zero(dx_, Num);
343  return *this;
344  }
345 
348  Expr& operator=(const Expr& x) {
349  if (this != &x) {
350  // Copy value
351  val_ = x.val_;
352 
353  // Copy dx_
354  //ss_array<T>::copy(x.dx_, dx_, Num);
355  for (int i=0; i<Num; i++)
356  dx_[i] = x.dx_[i];
357  }
358  return *this;
359  }
360 
362  template <typename S>
364  SACADO_ENABLE_EXPR_FUNC(Expr&) operator=(const Expr<S>& x) {
365 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
366  if (x.size() != Num)
367  throw "SELRFad::operator=() Error: Attempt to assign with incompatible sizes";
368 #endif
369 
370  // Compute partials
371  LocalAccumOp< Expr<S> > op(x);
372 
373  // Compute each tangent direction
374  for(int i=0; i<Num; ++i) {
375  op.t = T(0.);
376  op.i = i;
377 
378  // Automatically unrolled loop that computes
379  // for (int j=0; j<N; j++)
380  // op.t += op.partials[j] * x.getTangent<j>(i);
382 
383  dx_[i] = op.t;
384  }
385 
386  // Compute value
387  val_ = x.val();
388 
389  return *this;
390  }
391 
393 
398 
400  template <typename S>
402  SACADO_ENABLE_VALUE_FUNC(Expr&) operator += (const S& v) {
403  this->val() += v;
404  return *this;
405  }
406 
408  template <typename S>
410  SACADO_ENABLE_VALUE_FUNC(Expr&) operator -= (const S& v) {
411  this->val() -= v;
412  return *this;
413  }
414 
416  template <typename S>
418  SACADO_ENABLE_VALUE_FUNC(Expr&) operator *= (const S& v) {
419  this->val() *= v;
420  for (int i=0; i<Num; ++i)
421  dx_[i] *= v;
422  return *this;
423  }
424 
426  template <typename S>
428  SACADO_ENABLE_VALUE_FUNC(Expr&) operator /= (const S& v) {
429  this->val() /= v;
430  for (int i=0; i<Num; ++i)
431  dx_[i] /= v;
432  return *this;
433  }
434 
436  template <typename S>
438  SACADO_ENABLE_EXPR_FUNC(Expr&) operator += (const Expr<S>& x) {
439 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
440  if (x.size() != Num)
441  throw "SELRFad::operator+=() Error: Attempt to assign with incompatible sizes";
442 #endif
443 
444  // Compute partials
445  LocalAccumOp< Expr<S> > op(x);
446 
447  // Compute each tangent direction
448  for(int i=0; i<Num; ++i) {
449  op.t = T(0.);
450  op.i = i;
451 
452  // Automatically unrolled loop that computes
453  // for (int j=0; j<N; j++)
454  // op.t += op.partials[j] * x.getTangent<j>(i);
456 
457  dx_[i] += op.t;
458  }
459 
460  // Compute value
461  val_ += x.val();
462 
463  return *this;
464  }
465 
467  template <typename S>
469  SACADO_ENABLE_EXPR_FUNC(Expr&) operator -= (const Expr<S>& x) {
470 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
471  if (x.size() != Num)
472  throw "SELRFad::operator-=() Error: Attempt to assign with incompatible sizes";
473 #endif
474 
475  // Compute partials
476  LocalAccumOp< Expr<S> > op(x);
477 
478  // Compute each tangent direction
479  for(int i=0; i<Num; ++i) {
480  op.t = T(0.);
481  op.i = i;
482 
483  // Automatically unrolled loop that computes
484  // for (int j=0; j<N; j++)
485  // op.t += op.partials[j] * x.getTangent<j>(i);
487 
488  dx_[i] -= op.t;
489  }
490 
491  // Compute value
492  val_ -= x.val();
493 
494  return *this;
495  }
496 
498  template <typename S>
500  SACADO_ENABLE_EXPR_FUNC(Expr&) operator *= (const Expr<S>& x) {
501  T xval = x.val();
502 
503 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
504  if (x.size() != Num)
505  throw "SELRFad::operator*=() Error: Attempt to assign with incompatible sizes";
506 #endif
507 
508  // Compute partials
509  LocalAccumOp< Expr<S> > op(x);
510 
511  // Compute each tangent direction
512  for(int i=0; i<Num; ++i) {
513  op.t = T(0.);
514  op.i = i;
515 
516  // Automatically unrolled loop that computes
517  // for (int j=0; j<N; j++)
518  // op.t += op.partials[j] * x.getTangent<j>(i);
520 
521  dx_[i] = val_ * op.t + dx_[i] * xval;
522  }
523 
524  // Compute value
525  val_ *= xval;
526 
527  return *this;
528  }
529 
531  template <typename S>
533  SACADO_ENABLE_EXPR_FUNC(Expr&) operator /= (const Expr<S>& x) {
534  T xval = x.val();
535 
536 #if defined(SACADO_DEBUG) && !defined(__CUDA_ARCH__ )
537  if (x.size() != Num)
538  throw "SELRFad::operator/=() Error: Attempt to assign with incompatible sizes";
539 #endif
540 
541  // Compute partials
542  LocalAccumOp< Expr<S> > op(x);
543 
544  T xval2 = xval*xval;
545 
546  // Compute each tangent direction
547  for(int i=0; i<Num; ++i) {
548  op.t = T(0.);
549  op.i = i;
550 
551  // Automatically unrolled loop that computes
552  // for (int j=0; j<N; j++)
553  // op.t += op.partials[j] * x.getTangent<j>(i);
555 
556  dx_[i] = (dx_[i] * xval - val_ * op.t) / xval2;
557  }
558 
559  // Compute value
560  val_ /= xval;
561 
562  return *this;
563  }
564 
566 
567  protected:
568 
570  T dx_[Num];
571 
574 
575  // Functor for mpl::for_each to compute the local accumulation
576  // of a tangent derivative
577  //
578  // We use getTangent<>() to get dx components from expression
579  // arguments instead of getting the argument directly or extracting
580  // the dx array due to striding in ViewFad (or could use striding
581  // directly here if we need to get dx array).
582  template <typename ExprT>
583  struct LocalAccumOp {
584  typedef typename ExprT::value_type value_type;
585  static const int N = ExprT::num_args;
586  const ExprT& x;
587  mutable value_type t;
588  value_type partials[N];
589  int i;
591  LocalAccumOp(const ExprT& x_) : x(x_) {
592  x.computePartials(value_type(1.), partials);
593  }
595  void getTangents(int i_) { i = i_; }
596  template <typename ArgT>
598  void operator () (ArgT arg) const {
599  const int Arg = ArgT::value;
600  if (x.template isActive<Arg>())
601  t += partials[Arg] * x.template getTangent<Arg>(i);
602  }
603  };
604 
605  }; // class Expr<SFadExprTag>
606 
607  } // namespace ELRFad
608 
609 } // namespace Sacado
610 
611 #define FAD_NS ELRFad
612 #include "Sacado_Fad_SFad_tmpl.hpp"
613 #undef FAD_NS
614 
615 #include "Sacado_ELRFad_ViewFad.hpp"
616 #include "Sacado_ELRFad_Ops.hpp"
617 
618 #endif // SACADO_ELRFAD_SFAD_HPP
SACADO_INLINE_FUNCTION bool updateValue() const
Return whether this Fad object has an updated value.
SACADO_INLINE_FUNCTION int size() const
Returns number of derivative components.
void f()
expr expr dx(i)
SACADO_INLINE_FUNCTION int availableSize() const
Returns number of derivative components that can be stored without reallocation.
SACADO_INLINE_FUNCTION const T & val() const
Returns value.
SFad< value_type, Num > base_expr_type
Typename of base-expressions.
SACADO_INLINE_FUNCTION const T & dx(int i) const
Returns derivative component i with bounds checking.
SACADO_INLINE_FUNCTION void setIsConstant(bool is_const)
Set whether variable is constant.
#define SACADO_ENABLE_VALUE_CTOR_DECL
RemoveConst< T >::type value_type
Typename of values.
SACADO_INLINE_FUNCTION T & fastAccessDx(int i)
Returns derivative component i without bounds checking.
SACADO_INLINE_FUNCTION bool isPassive() const
Returns true if derivative array is empty.
SACADO_INLINE_FUNCTION const T & getTangent(int i) const
Return tangent component i of argument Arg.
SACADO_INLINE_FUNCTION void expand(int sz)
Expand derivative array to size sz.
SACADO_INLINE_FUNCTION const T * dx() const
Returns derivative array.
expr bar
#define SACADO_ENABLE_EXPR_CTOR_DECL
SACADO_INLINE_FUNCTION Expr(const Expr &x)
Copy constructor.
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 S &x, SACADO_ENABLE_VALUE_CTOR_DECL)
Constructor with supplied value x.
SACADO_INLINE_FUNCTION void setUpdateValue(bool update_val)
Set whether this Fad object should update values.
SACADO_INLINE_FUNCTION Expr(const Expr< S > &x, SACADO_ENABLE_EXPR_CTOR_DECL)
Copy constructor from any Expression object.
SACADO_INLINE_FUNCTION void resize(int sz)
Resize derivative array to length sz.
SACADO_INLINE_FUNCTION bool isActive() const
Return whether argument is active.
SACADO_INLINE_FUNCTION void diff(const int ith, const int n)
Set Fad object as the ith independent variable.
expr val()
#define T
Definition: Sacado_rad.hpp:553
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 const value_type * getDx(int j) const
Get dx array.
#define SACADO_ENABLE_VALUE_FUNC(RETURN_TYPE)
SACADO_INLINE_FUNCTION T & val()
Returns value.
Base template specification for testing equivalence.
static double x_
SACADO_INLINE_FUNCTION void getTangents(int i, value_type dots[]) const
Return tangent component i of arguments.
const int N
#define SACADO_ENABLE_EXPR_FUNC(RETURN_TYPE)
SACADO_INLINE_FUNCTION void cache() const
Cache values.
DerivInit
Enum use to signal whether the derivative array should be initialized in AD object constructors...
int value
Wrapper for a generic expression template.
ScalarType< value_type >::type scalar_type
Typename of scalar&#39;s (which may be different from T)
SACADO_INLINE_FUNCTION const T & fastAccessDx(int i) const
Returns derivative component i without bounds checking.
SACADO_INLINE_FUNCTION void computePartials(const T &bar, value_type partials[]) const
Return partials w.r.t. arguments.
static SACADO_INLINE_FUNCTION void zero(T *dest, int sz)
Zero out array dest of length sz.
Initialize the derivative array.
SACADO_INLINE_FUNCTION Expr()
Default constructor.
SACADO_INLINE_FUNCTION Expr(const int sz, const T &x, const DerivInit zero_out=InitDerivArray)
Constructor with size sz and value x.
#define SACADO_INLINE_FUNCTION
SACADO_INLINE_FUNCTION ~Expr()
Destructor.
SACADO_INLINE_FUNCTION void zero()
Zero out the derivative array.
SACADO_INLINE_FUNCTION bool hasFastAccess() const
Returns true if derivative array is not empty.
A tag for specializing Expr for SFad expressions.