1 #ifndef AUTO_DERIVATIVE_H 2 #define AUTO_DERIVATIVE_H 6 #include <boost/operators.hpp> 7 #include <boost/foreach.hpp> 44 #include <blitz/array.h> 67 else if(grad.rows() == D.
gradient().rows())
71 e <<
"Size of gradient in AutoDerivative doesn't match value you " 72 <<
"are trying to assign. Size of destination is " << grad.rows()
73 <<
" and size of source is " << D.
gradient().rows();
81 const blitz::Array<T, 1>&
gradient()
const {
return grad; }
160 { Os <<
"AutoDerivativeRef\n" 161 <<
" Value: " <<
value() <<
"\n" 162 <<
" Gradient:\n" << gradient() <<
"\n";
168 mutable blitz::Array<T, 1> grad;
208 boost::totally_ordered<class AutoDerivative<T> >,
209 boost::totally_ordered<class AutoDerivative<T>, T>
227 : val(Val), grad(G) {}
233 : val(V.
value()), grad(V.gradient().copy()) { }
241 : val(Val), grad(nvars)
262 : val(D.val), grad(D.grad.copy())
274 if(grad.rows() == D.grad.rows())
277 grad.reference(D.grad.copy());
292 const T&
value()
const {
return val;}
299 const blitz::Array<T, 1>&
gradient()
const {
return grad; }
318 bool operator<(const AutoDerivative<T>& V)
const {
return val < V.val;}
333 grad.reference(V.grad.copy());
338 { val += V;
return *
this;}
347 grad.resize(V.grad.shape());
354 { val -= V;
return *
this;}
361 grad = V.val * grad + val * V.grad;
363 grad.reference(V.grad.copy());
372 { val *= V; grad *= V;
return *
this;}
379 grad = 1 / V.val * grad - val / (V.val * V.val) * V.grad;
381 grad.resize(V.grad.shape());
382 grad = - val / (V.val * V.val) * V.grad;
390 { val /= V; grad /= V;
return *
this;}
392 { Os <<
"AutoDerivative\n" 393 <<
" Value: " << val <<
"\n" 394 <<
" Gradient:\n" << grad <<
"\n";
475 blitz::Array<T, 1> grad;
484 template<
class T>
inline blitz::Array<T, 2>
jacobian 493 blitz::Array<T, 2> res(Ad.rows(), nvar);
495 for(
int i = 0; i < Ad.rows(); ++i)
496 if(!Ad(i).is_constant())
497 res(i, blitz::Range::all()) = Ad(i).gradient();
499 res(i, blitz::Range::all()) = 0;
504 template<
class T>
inline blitz::Array<T, 3>
jacobian 513 blitz::Array<T, 3> res(Ad.rows(), Ad.cols(), nvar);
515 for(
int i = 0; i < Ad.rows(); ++i)
516 for(
int j = 0; j < Ad.cols(); ++j)
517 if(!Ad(i, j).is_constant())
518 res(i, j, blitz::Range::all()) = Ad(i, j).gradient();
520 res(i, j, blitz::Range::all()) = 0;
525 template<
class T>
inline blitz::Array<T, 4>
jacobian 534 blitz::Array<T, 4> res(Ad.rows(), Ad.cols(), Ad.depth(), nvar);
536 for(
int i = 0; i < Ad.rows(); ++i)
537 for(
int j = 0; j < Ad.cols(); ++j)
538 for(
int k = 0; k < Ad.depth(); ++k)
539 if(!Ad(i, j, k).is_constant())
540 res(i, j, k, blitz::Range::all()) = Ad(i, j, k).gradient();
542 res(i, j, k, blitz::Range::all()) = 0;
547 template<
class T>
inline blitz::Array<T, 5>
jacobian 556 blitz::Array<T, 5> res(Ad.rows(), Ad.cols(), Ad.depth(),
557 Ad.extent(blitz::fourthDim), nvar);
559 for(
int i = 0; i < Ad.rows(); ++i)
560 for(
int j = 0; j < Ad.cols(); ++j)
561 for(
int k = 0; k < Ad.depth(); ++k)
562 for(
int m = 0;
m < Ad.extent(blitz::fourthDim); ++
m)
563 if(!Ad(i, j, k,
m).is_constant())
564 res(i, j, k,
m, blitz::Range::all()) = Ad(i, j, k,
m).gradient();
566 res(i, j, k,
m, blitz::Range::all()) = 0;
577 (
const blitz::Array<double, 1>& Val,
const blitz::Array<double, 2>& Jac)
579 blitz::Array<AutoDerivative<double>, 1> res(Val.shape());
580 for(
int i = 0; i < Val.rows(); ++i) {
581 res(i).value() = Val(i);
583 res(i).gradient().reference(Jac(i, blitz::Range::all()));
589 (
const blitz::Array<double, 1>& Val,
int i_th,
int nvars)
591 blitz::Array<AutoDerivative<double>, 1> res(Val.shape());
592 for(
int i = 0; i < Val.rows(); ++i)
598 (
const blitz::Array<double, 2>& Val,
const blitz::Array<double, 3>& Jac)
600 blitz::Array<AutoDerivative<double>, 2> res(Val.shape());
601 for(
int i = 0; i < Val.rows(); ++i)
602 for(
int j = 0; j < Val.cols(); ++j) {
603 res(i, j).value() = Val(i, j);
605 res(i, j).gradient().reference(Jac(i, j, blitz::Range::all()));
611 (
const blitz::Array<double, 3>& Val,
const blitz::Array<double, 4>& Jac)
613 blitz::Array<AutoDerivative<double>, 3> res(Val.shape());
614 for(
int i = 0; i < Val.rows(); ++i)
615 for(
int j = 0; j < Val.cols(); ++j)
616 for(
int k = 0; k < Val.extent(blitz::thirdDim); ++k) {
617 res(i, j, k).value() = Val(i, j, k);
618 if(Jac.extent(blitz::fourthDim) > 0)
619 res(i, j, k).gradient().reference(Jac(i, j, k, blitz::Range::all()));
637 blitz::Array<double, 1>(x.
gradient() / (2*::sqrt(x.
value())) ));
657 blitz::Array<double, 1>(M_LOG10E * x.
gradient() / x.
value()));
686 err_msg <<
"Value not within domain of arcsine: -1 <= x <= 1 where x = " << x.
value();
705 blitz::Array<double, 1>(x.
gradient() * (- ::sin(x.
value())) ));
714 err_msg <<
"Value not within domain of arccosine: -1 <= x <= 1 where x = " << x.
value();
755 blitz::Array<double, 1>( base.
gradient() * exponent *
pow(base.
value(), exponent - 1) ));
766 blitz::Array<double, 1>( exponent.
gradient() * ::log(base) *
::pow(base, exponent.
value()) ));
779 {
return Ad.
value(); }
794 blitz::Array<double, 1>( base.
gradient() * 2 * base.
value()));
AutoDerivative< T > & operator=(const AutoDerivative< T > &D)
Assignment operator. This makes a deep copy.
friend AutoDerivative< T > operator+(const AutoDerivative< T > &X, const AutoDerivative< T > &Y)
#define range_check(V, Min, Max)
Range check.
AutoDerivative(const T &Val, int i_th, int nvars)
Constructor for a value of the i_th independent variable (0 based).
friend AutoDerivative< T > operator/(const T &X, const AutoDerivative< T > &Y)
AutoDerivative< T > & operator+=(const T &V)
void print(std::ostream &Os) const
friend AutoDerivative< T > operator*(const T &X, const AutoDerivativeRef< T > &Y)
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...
AutoDerivative< T > & operator+=(const AutoDerivative< T > &V)
friend AutoDerivative< T > operator/(const AutoDerivative< T > &X, const AutoDerivative< T > &Y)
bool is_constant() const
Is this object a constant (with a gradient() all zeros)?
AutoDerivative< T > & operator*=(const AutoDerivative< T > &V)
AutoDerivative()
Default constructor, data is uninitialized.
FullPhysics::AutoDerivative< double > sqrt(const FullPhysics::AutoDerivative< double > &x)
friend AutoDerivative< T > operator+(const T &X, const AutoDerivative< T > &Y)
bool operator<(const T &V) const
FullPhysics::AutoDerivative< double > acos(const FullPhysics::AutoDerivative< double > &x)
bool operator>(const AutoDerivative< T > &V) const
AutoDerivative(const AutoDerivativeRef< T > &V)
Convert AutoDerivativeRef to a AutoDerivative.
friend AutoDerivative< T > operator+(const AutoDerivativeRef< T > &X, const T &Y)
friend AutoDerivative< T > operator-(const AutoDerivativeRef< T > &X, const T &Y)
AutoDerivative(const T &Val, const blitz::Array< T, 1 > &G)
Constructor that takes a value and a gradient.
This is the base of the exception hierarchy for Full Physics code.
friend AutoDerivative< T > operator*(const AutoDerivative< T > &X, const T &Y)
blitz::Array< T, 2 > jacobian(const blitz::Array< AutoDerivative< T >, 1 > &Ad)
Utility function to extract the Jacobian as a separate matrix from an array of AutoDerivative.
FullPhysics::AutoDerivative< double > asin(const FullPhysics::AutoDerivative< double > &x)
friend AutoDerivative< T > operator*(const AutoDerivativeRef< T > &X, const T &Y)
BZ_DECLARE_FUNCTION_RET(auto_derivative, FullPhysics::AutoDerivative< double >)
AutoDerivativeRef(T &V, const blitz::Array< T, 1 > &G)
const blitz::Array< T, 1 > & gradient() const
bool operator==(const AutoDerivative< T > &V) const
AutoDerivative(const AutoDerivative< T > &D)
Copy constructor. This does a deep copy.
blitz::Array< T, 1 > & gradient_ref() const
Helper class that gives us a reference that we can assign a AutoDerivative to and write into the corr...
This is a Mixin for classes that can be printed.
AutoDerivative< T > & operator/=(const T &V)
friend AutoDerivative< T > operator-(const AutoDerivative< T > &X)
Apply value function to a blitz array.
friend AutoDerivative< T > operator*(const T &X, const AutoDerivative< T > &Y)
friend AutoDerivative< T > operator+(const AutoDerivativeRef< T > &X, const AutoDerivativeRef< T > &Y)
bool operator==(const T &V) const
bool operator>(const T &V) const
There are a number of tools that can be used to do "Automatic Differentiation" (see for example http:...
friend AutoDerivative< T > operator/(const AutoDerivative< T > &X, const T &Y)
friend AutoDerivative< T > operator-(const AutoDerivativeRef< T > &X, const AutoDerivativeRef< T > &Y)
void print(std::ostream &Os) const
friend AutoDerivative< T > operator*(const AutoDerivative< T > &X, const AutoDerivative< T > &Y)
FullPhysics::AutoDerivative< double > pow2(const FullPhysics::AutoDerivative< double > &x)
const Unit m("m", 1.0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
int number_variable() const
Number of variables in gradient.
const blitz::Array< T, 1 > & gradient() const
Gradient.
Unit pow(const Unit &Dunit, const boost::rational< int > &Exponent)
FullPhysics::AutoDerivative< double > atan(const FullPhysics::AutoDerivative< double > &x)
AutoDerivative< T > copy() const
Create deep copy.
friend AutoDerivative< T > operator+(const T &X, const AutoDerivativeRef< T > &Y)
const AutoDerivativeRef< T > & operator=(const AutoDerivative< T > &D) const
blitz::Array< T, 1 > & gradient()
friend AutoDerivative< T > operator/(const AutoDerivativeRef< T > &X, const AutoDerivativeRef< T > &Y)
AutoDerivative< T > & operator-=(const AutoDerivative< T > &V)
friend AutoDerivative< T > operator-(const AutoDerivativeRef< T > &X)
Contains classes to abstract away details in various Spurr Radiative Transfer software.
const T & value() const
Convert to type T.
FullPhysics::AutoDerivative< double > log10(const FullPhysics::AutoDerivative< double > &x)
friend AutoDerivative< T > operator-(const T &X, const AutoDerivative< T > &Y)
friend AutoDerivative< T > operator+(const AutoDerivative< T > &X, const T &Y)
friend AutoDerivative< T > operator*(const AutoDerivativeRef< T > &X, const AutoDerivativeRef< T > &Y)
friend AutoDerivative< T > operator-(const T &X, const AutoDerivativeRef< T > &Y)
AutoDerivative< T > & operator-=(const T &V)
FullPhysics::AutoDerivative< double > cos(const FullPhysics::AutoDerivative< double > &x)
friend AutoDerivative< T > operator-(const AutoDerivative< T > &X, const T &Y)
FullPhysics::AutoDerivative< double > exp(const FullPhysics::AutoDerivative< double > &x)
AutoDerivative< T > & operator*=(const T &V)
AutoDerivative< T > & operator/=(const AutoDerivative< T > &V)
friend AutoDerivative< T > operator/(const T &X, const AutoDerivativeRef< T > &Y)
friend AutoDerivative< T > operator/(const AutoDerivativeRef< T > &X, const T &Y)
double value(const FullPhysics::AutoDerivative< double > &Ad)
AutoDerivative(const T &Val)
Constructor for a value that is a constant.
friend AutoDerivative< T > operator-(const AutoDerivative< T > &X, const AutoDerivative< T > &Y)
FullPhysics::AutoDerivative< double > tan(const FullPhysics::AutoDerivative< double > &x)
FullPhysics::AutoDerivative< double > sin(const FullPhysics::AutoDerivative< double > &x)
FullPhysics::AutoDerivative< double > log(const FullPhysics::AutoDerivative< double > &x)