ReFRACtor
array_ad.h
Go to the documentation of this file.
1 #ifndef ARRAY_AD_H
2 #define ARRAY_AD_H
3 #include "auto_derivative.h"
4 #include "fp_exception.h"
5 #include <blitz/tinyvec-et.h>
6 
7 // Turn on trace messages, useful for debugging problems with this class.
8 // #define ARRAY_AD_DIAGNOSTIC
9 #ifdef ARRAY_AD_DIAGNOSTIC
10 #define ARRAY_AD_DIAGNOSTIC_MSG std::cerr << "In " << __LINE__ << "\n"
11 #else
12 #define ARRAY_AD_DIAGNOSTIC_MSG
13 #endif
14 
15 namespace FullPhysics {
16 /****************************************************************/
40 template<class T, int D> class ArrayAd
41 {
42 public:
43  ArrayAd(const blitz::Array<AutoDerivative<T>, D>& V)
44  : val(V.shape()), jac(FullPhysics::jacobian(V)),
45  is_const(false)
46  {
48  if(number_variable() ==0)
49  resize(V.shape(), 0);
50  val = blitz::value(V);
51  }
53  : val(V.val), jac(V.jac), is_const(V.is_const)
54  {
56  }
58  {
60  if(val.rows() ==0) { // Special handling for new empty objects
61  val.reference(V.val.copy());
62  jac.reference(V.jac.copy());
63  is_const = V.is_const;
64  } else {
65  val = V.val;
66  if(V.is_const) {
67  if(!is_const)
68  jac = 0;
69  } else {
70  // This is such a common error, add a check here.
71  if(number_variable() != V.number_variable()) {
72  Exception e;
73  e << "Trying to assign Jacobian with " << V.number_variable()
74  << " variables to size " << number_variable() << "\n";
75  throw e;
76  }
77  jac = V.jac;
78  }
79  }
80  return *this;
81  }
82  ArrayAd(const blitz::Array<T, D>& Val, const blitz::Array<T, D+1>& Jac,
83  bool Is_const = false, bool Force_copy = false)
84  : val(Force_copy ? Val.copy() : Val),
85  jac(Force_copy ? Jac.copy() : Jac), is_const(Is_const)
86  {
88  if(jac.extent(D) == 0) {
89  is_const = true;
90  blitz::TinyVector<int, D + 1> s2;
91  for(int i = 0; i < D; ++i)
92  s2(i) = val.shape()(i);
93  s2(D) = 1;
94  jac.resize(s2);
95  jac = 0;
96  }
97  }
98  ArrayAd(const blitz::Array<T, D>& Val, bool Force_copy = false)
99  : val(Force_copy ? Val.copy() : Val), is_const(true)
100  {
102  blitz::TinyVector<int, D + 1> s2;
103  for(int i = 0; i < D; ++i)
104  s2(i) = val.shape()(i);
105  s2(D) = 1;
106  jac.resize(s2);
107  jac = 0;
108  }
109  ArrayAd(const blitz::Array<T, D>& Val, int nvar, bool Force_copy = false)
110  : val(Force_copy ? Val.copy() : Val), is_const(nvar == 0)
111  {
112  blitz::TinyVector<int, D + 1> s2;
113  for(int i = 0; i < D; ++i)
114  s2(i) = val.shape()(i);
115  s2(D) = nvar;
116  jac.resize(s2);
117  if(is_const)
118  jac = 0;
119  }
120  ArrayAd() :val(0), jac(0,1), is_const(false) {}
121  ArrayAd(int n1, int nvar)
122  : val(n1), jac(n1, std::max(nvar, 1)), is_const(nvar == 0)
123  {
124  if(is_const)
125  jac = 0;
126  }
127  ArrayAd(int n1, int n2, int nvar)
128  : val(n1, n2), jac(n1, n2, std::max(nvar, 1)), is_const(nvar == 0)
129  {
130  if(is_const)
131  jac = 0;
132  }
133  ArrayAd(int n1, int n2, int n3, int nvar)
134  : val(n1, n2, n3), jac(n1, n2, n3, std::max(nvar, 1)),
135  is_const(nvar == 0)
136  {
137  if(is_const)
138  jac = 0;
139  }
140  ArrayAd(int n1, int n2, int n3, int n4, int nvar)
141  : val(n1, n2, n3, n4), jac(n1, n2, n3, n4, std::max(nvar, 1)),
142  is_const(nvar == 0)
143  {
144  if(is_const)
145  jac = 0;
146  }
147  ArrayAd(int n1, int n2, int n3, int n4, int n5, int nvar)
148  : val(n1, n2, n3, n4, n5), jac(n1, n2, n3, n4, n5, std::max(nvar, 1)),
149  is_const(nvar == 0)
150  {
151  if(is_const)
152  jac = 0;
153  }
154  ArrayAd(const blitz::TinyVector<int, D>& Shape, int nvar)
155  : val(Shape), is_const(nvar == 0)
156  {
157  blitz::TinyVector<int, D + 1> s2;
158  for(int i = 0; i < D; ++i)
159  s2(i) = Shape(i);
160  s2(D) = std::max(nvar, 1);
161  jac.resize(s2);
162  if(is_const)
163  jac = 0;
164  }
165  void resize_number_variable(int nvar)
166  {
167  if(nvar == number_variable())
168  return;
169  blitz::TinyVector<int, D + 1> s2;
170  for(int i = 0; i < D; ++i)
171  s2(i) = val.shape()(i);
172  s2(D) = std::max(nvar, 1);
173  jac.resize(s2);
174  jac = 0;
175  is_const = (nvar ==0);
176  }
177  void resize(const blitz::TinyVector<int, D>& Shape, int nvar)
178  {
179  val.resize(Shape);
180  is_const = (nvar ==0);
181  blitz::TinyVector<int, D + 1> s2;
182  for(int i = 0; i < D; ++i)
183  s2(i) = Shape(i);
184  s2(D) = std::max(nvar, 1);
185  jac.resize(s2);
186  if(is_const)
187  jac = 0;
188  }
189  void resize(int n1, int nvar)
190  {
191  val.resize(n1); jac.resize(n1, std::max(nvar, 1));
192  is_const = (nvar == 0);
193  if(is_const)
194  jac = 0;
195  }
196  void resize(int n1, int n2, int nvar)
197  {
198  val.resize(n1, n2); jac.resize(n1, n2, std::max(nvar, 1));
199  is_const = (nvar == 0);
200  if(is_const)
201  jac = 0;
202  }
203  void resize(int n1, int n2, int n3, int nvar)
204  {
205  val.resize(n1, n2, n3); jac.resize(n1, n2, n3, std::max(nvar, 1));
206  is_const = (nvar == 0);
207  if(is_const)
208  jac = 0;
209  }
210  void resize(int n1, int n2, int n3, int n4, int nvar)
211  {
212  val.resize(n1, n2, n3, n4);
213  jac.resize(n1, n2, n3, n4, std::max(nvar, 1));
214  is_const = (nvar == 0);
215  if(is_const)
216  jac = 0;
217  }
218  void resize(int n1, int n2, int n3, int n4, int n5, int nvar)
219  {
220  val.resize(n1, n2, n3, n4, n5);
221  jac.resize(n1, n2, n3, n4, n5, std::max(nvar, 1));
222  is_const = (nvar == 0);
223  if(is_const)
224  jac = 0;
225  }
227  {
228  if(is_const)
229  return AutoDerivativeRef<T>(val(i1));
230  else
231  return AutoDerivativeRef<T>(val(i1),
232  jac(i1, blitz::Range::all()));
233  }
235  {
236  if(is_const)
237  return AutoDerivativeRef<T>(val(i1, i2));
238  else
239  return AutoDerivativeRef<T>(val(i1, i2),
240  jac(i1, i2, blitz::Range::all()));
241  }
242  AutoDerivativeRef<T> operator()(int i1, int i2, int i3)
243  {
244  if(is_const)
245  return AutoDerivativeRef<T>(val(i1, i2, i3));
246  else
247  return AutoDerivativeRef<T>(val(i1, i2, i3),
248  jac(i1, i2, i3, blitz::Range::all()));
249  }
250  AutoDerivativeRef<T> operator()(int i1, int i2, int i3, int i4)
251  {
252  if(is_const)
253  return AutoDerivativeRef<T>(val(i1, i2, i3, i4));
254  else
255  return AutoDerivativeRef<T>(val(i1, i2, i3, i4),
256  jac(i1, i2, i3, i4, blitz::Range::all()));
257  }
258  AutoDerivativeRef<T> operator()(int i1, int i2, int i3, int i4, int i5)
259  {
260  if(is_const)
261  return AutoDerivativeRef<T>(val(i1, i2, i3, i4, i5));
262  else
263  return AutoDerivativeRef<T>(val(i1, i2, i3, i4, i5),
264  jac(i1, i2, i3, i4, i5, blitz::Range::all()));
265  }
267  {
268  if(is_const)
269  return AutoDerivative<T>(val(i1));
270  else
271  return AutoDerivative<T>(val(i1),
272  jac(i1, blitz::Range::all()));
273  }
274  AutoDerivative<T> operator()(int i1, int i2) const
275  {
276  if(is_const)
277  return AutoDerivative<T>(val(i1, i2));
278  else
279  return AutoDerivative<T>(val(i1, i2),
280  jac(i1, i2, blitz::Range::all()));
281  }
282  AutoDerivative<T> operator()(int i1, int i2, int i3) const
283  {
284  if(is_const)
285  return AutoDerivative<T>(val(i1, i2, i3));
286  else
287  return AutoDerivative<T>(val(i1, i2, i3),
288  jac(i1, i2, i3, blitz::Range::all()));
289  }
290  AutoDerivative<T> operator()(int i1, int i2, int i3, int i4) const
291  {
292  if(is_const)
293  return AutoDerivative<T>(val(i1, i2, i3, i4));
294  else
295  return AutoDerivative<T>(val(i1, i2, i3, i4),
296  jac(i1, i2, i3, i4, blitz::Range::all()));
297  }
298  AutoDerivative<T> operator()(int i1, int i2, int i3, int i4, int i5) const
299  {
300  if(is_const)
301  return AutoDerivative<T>(val(i1, i2, i3, i4, i5));
302  else
303  return AutoDerivative<T>(val(i1, i2, i3, i4, i5),
304  jac(i1, i2, i3, i4, i5, blitz::Range::all()));
305  }
306  const blitz::Array<T, D>& value() const {return val;}
307  const blitz::Array<T, D+1> jacobian() const
308  {
309  if(is_const)
310  return blitz::Array<T, D+1>();
311  return jac;
312  }
313  blitz::Array<T, D>& value() {return val;}
314  blitz::Array<T, D+1>& jacobian()
315  { return jac;}
316  blitz::Array<AutoDerivative<T>, D> to_array() const
317  { if(!is_const)
318  return auto_derivative(val, jac);
319  blitz::Array<AutoDerivative<T>, D> res(val.shape());
320  res = auto_derivative(val);
321  return res;
322  }
323  ArrayAd& operator=(const blitz::Array<T, D>& V)
324  { ARRAY_AD_DIAGNOSTIC_MSG; val = V; jac = 0; return *this; }
325  ArrayAd& operator=(const T& V)
326  { ARRAY_AD_DIAGNOSTIC_MSG; val = V; jac = 0; return *this; }
329  val = V.value();
330  blitz::IndexPlaceholder<D> ig;
331  if(!is_constant())
332  jac = V.gradient()(ig);
333  return *this;
334  }
335  ArrayAd<T, 1> operator()(const blitz::Range& r1) const
336  {
337  return ArrayAd<T, 1>(val(r1), jac(r1, blitz::Range::all()), is_const);
338  }
339  template<typename T1, typename T2>
341  {
343  (val(r1, r2), jac(r1, r2, blitz::Range::all()), is_const);
344  }
345  template<typename T1, typename T2, typename T3>
347  operator()(T1 r1, T2 r2, T3 r3) const
348  {
350  (val(r1, r2, r3), jac(r1, r2, r3, blitz::Range::all()), is_const);
351  }
352  template<typename T1, typename T2, typename T3, typename T4>
354  operator()(T1 r1, T2 r2, T3 r3, T4 r4) const
355  {
357  (val(r1, r2, r3, r4), jac(r1, r2, r3, r4, blitz::Range::all()),
358  is_const);
359  }
360  template<typename T1, typename T2, typename T3, typename T4, typename T5>
362  operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5) const
363  {
365  (val(r1, r2, r3, r4, r5), jac(r1, r2, r3, r4, r5, blitz::Range::all()),
366  is_const);
367  }
368  int rows() const {return val.rows();}
369  int cols() const {return val.cols();}
370  int depth() const {return val.depth();}
371  bool is_constant() const {return is_const;}
372  void reference(const ArrayAd<T, D>& V)
373  { val.reference(V.val); jac.reference(V.jac); is_const = V.is_const;}
375  { return ArrayAd<T,D>(val.copy(), jac.copy(), is_const); }
376  int number_variable() const
377  {
378  if(is_const)
379  return 0;
380  else
381  return jac.extent(D);
382  }
383  const blitz::TinyVector<int, D>& shape() const { return val.shape(); }
384  friend std::ostream& operator<<(std::ostream& os,
385  const ArrayAd<T, D>& V)
386  { os << V.val << "\n" << V.jac << "\n"; return os;}
387  friend std::istream& operator>>(std::istream& is, ArrayAd<T, D>& V)
388  { is >> V.val >> V.jac; return is; }
389 
391  //-----------------------------------------------------------------------
392  inline bool operator==(const ArrayAd<T, D>& A) const
393  {
394  return blitz::all(A.val == this->val) &&
395  blitz::all(A.jac == this->jac) &&
396  A.val.dimensions() == this->val.dimensions() &&
397  A.jac.dimensions() == this->jac.dimensions() &&
398  blitz::all(A.val.shape() == this->val.shape()) &&
399  blitz::all(A.jac.shape() == this->jac.shape());
400 
401  }
402  inline bool operator!=(const ArrayAd<T, D>& A) const
403  { return !(A == *this); }
404 
405 private:
406  blitz::Array<T, D> val;
407  blitz::Array<T, D + 1> jac;
408  bool is_const;
409 };
410 }
411 #endif
412 
#define ARRAY_AD_DIAGNOSTIC_MSG
Definition: array_ad.h:12
void resize_number_variable(int nvar)
Definition: array_ad.h:165
blitz::Array< T, D+1 > & jacobian()
Definition: array_ad.h:314
int cols() const
Definition: array_ad.h:369
blitz::Array< T, D > & value()
Definition: array_ad.h:313
blitz::Array< AutoDerivative< double >, 1 > auto_derivative(const blitz::Array< double, 1 > &Val, const blitz::Array< double, 2 > &Jac)
Utility routine to take value and Jacobian separately and create a blitz::Array<AutoDerivative<double...
bool is_constant() const
Definition: array_ad.h:371
ArrayAd(const blitz::Array< T, D > &Val, bool Force_copy=false)
Definition: array_ad.h:98
int depth() const
Definition: array_ad.h:370
ArrayAd & operator=(const AutoDerivative< T > &V)
Definition: array_ad.h:327
bool operator==(const ArrayAd< T, D > &A) const
We define != in terms of this operator.
Definition: array_ad.h:392
ArrayAd & operator=(const T &V)
Definition: array_ad.h:325
AutoDerivative< T > operator()(int i1, int i2, int i3, int i4) const
Definition: array_ad.h:290
ArrayAd(int n1, int n2, int nvar)
Definition: array_ad.h:127
AutoDerivative< T > operator()(int i1) const
Definition: array_ad.h:266
ArrayAd(int n1, int n2, int n3, int n4, int n5, int nvar)
Definition: array_ad.h:147
void resize(int n1, int n2, int nvar)
Definition: array_ad.h:196
ArrayAd< T, blitz::SliceInfo< T, T1, T2, T3, T4 >::rank > operator()(T1 r1, T2 r2, T3 r3, T4 r4) const
Definition: array_ad.h:354
ArrayAd< T, blitz::SliceInfo< T, T1, T2 >::rank > operator()(T1 r1, T2 r2) const
Definition: array_ad.h:340
AutoDerivativeRef< T > operator()(int i1, int i2, int i3, int i4)
Definition: array_ad.h:250
void resize(int n1, int n2, int n3, int nvar)
Definition: array_ad.h:203
ArrayAd & operator=(const ArrayAd< T, D > &V)
Definition: array_ad.h:57
This is the base of the exception hierarchy for Full Physics code.
Definition: fp_exception.h:16
STL namespace.
AutoDerivative< T > operator()(int i1, int i2, int i3, int i4, int i5) const
Definition: array_ad.h:298
ArrayAd< T, blitz::SliceInfo< T, T1, T2, T3 >::rank > operator()(T1 r1, T2 r2, T3 r3) const
Definition: array_ad.h:347
friend std::istream & operator>>(std::istream &is, ArrayAd< T, D > &V)
Definition: array_ad.h:387
const blitz::Array< T, D+1 > jacobian() const
Definition: array_ad.h:307
void resize(int n1, int n2, int n3, int n4, int n5, int nvar)
Definition: array_ad.h:218
blitz::Array< AutoDerivative< T >, D > to_array() const
Definition: array_ad.h:316
Helper class that gives us a reference that we can assign a AutoDerivative to and write into the corr...
void resize(int n1, int n2, int n3, int n4, int nvar)
Definition: array_ad.h:210
const Unit A("A", 1.0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0)
AutoDerivativeRef< T > operator()(int i1)
Definition: array_ad.h:226
const blitz::Array< T, D > & value() const
Definition: array_ad.h:306
void resize(const blitz::TinyVector< int, D > &Shape, int nvar)
Definition: array_ad.h:177
AutoDerivative< T > operator()(int i1, int i2, int i3) const
Definition: array_ad.h:282
The AutoDerivative<T> works well, and it works with blitz if you create a blitz::Array<AutoDerivative...
Definition: array_ad.h:40
There are a number of tools that can be used to do "Automatic Differentiation" (see for example http:...
ArrayAd(int n1, int nvar)
Definition: array_ad.h:121
ArrayAd< T, D > copy() const
Definition: array_ad.h:374
ArrayAd(const blitz::Array< AutoDerivative< T >, D > &V)
Definition: array_ad.h:43
ArrayAd(const ArrayAd< T, D > &V)
Definition: array_ad.h:52
const blitz::Array< T, 1 > & gradient() const
Gradient.
AutoDerivative< T > operator()(int i1, int i2) const
Definition: array_ad.h:274
int number_variable() const
Definition: array_ad.h:376
void resize(int n1, int nvar)
Definition: array_ad.h:189
void reference(const ArrayAd< T, D > &V)
Definition: array_ad.h:372
AutoDerivativeRef< T > operator()(int i1, int i2, int i3, int i4, int i5)
Definition: array_ad.h:258
ArrayAd(int n1, int n2, int n3, int nvar)
Definition: array_ad.h:133
ArrayAd(const blitz::TinyVector< int, D > &Shape, int nvar)
Definition: array_ad.h:154
Contains classes to abstract away details in various Spurr Radiative Transfer software.
Definition: doxygen_python.h:1
ArrayAd< T, blitz::SliceInfo< T, T1, T2, T3, T4, T5 >::rank > operator()(T1 r1, T2 r2, T3 r3, T4 r4, T5 r5) const
Definition: array_ad.h:362
const T & value() const
Convert to type T.
const blitz::TinyVector< int, D > & shape() const
Definition: array_ad.h:383
AutoDerivativeRef< T > operator()(int i1, int i2)
Definition: array_ad.h:234
ArrayAd< T, 1 > operator()(const blitz::Range &r1) const
Definition: array_ad.h:335
AutoDerivativeRef< T > operator()(int i1, int i2, int i3)
Definition: array_ad.h:242
ArrayAd & operator=(const blitz::Array< T, D > &V)
Definition: array_ad.h:323
ArrayAd(const blitz::Array< T, D > &Val, const blitz::Array< T, D+1 > &Jac, bool Is_const=false, bool Force_copy=false)
Definition: array_ad.h:82
bool operator!=(const ArrayAd< T, D > &A) const
Definition: array_ad.h:402
double value(const FullPhysics::AutoDerivative< double > &Ad)
ArrayAd(const blitz::Array< T, D > &Val, int nvar, bool Force_copy=false)
Definition: array_ad.h:109
ArrayAd(int n1, int n2, int n3, int n4, int nvar)
Definition: array_ad.h:140
int rows() const
Definition: array_ad.h:368
friend std::ostream & operator<<(std::ostream &os, const ArrayAd< T, D > &V)
Definition: array_ad.h:384

Copyright © 2017, California Institute of Technology.
ALL RIGHTS RESERVED.
U.S. Government Sponsorship acknowledged.
Generated Fri Aug 24 2018 15:44:11