Prev Next Index-> contents reference index search external Up-> CppAD AD ADValued atomic checkpoint atomic_mul_level.cpp ADValued-> Arithmetic unary_standard_math binary_math CondExp Discrete numeric_limits atomic atomic-> checkpoint atomic_base checkpoint-> checkpoint.cpp atomic_mul_level.cpp checkpoint_ode.cpp checkpoint_extended_ode.cpp atomic_mul_level.cpp Headings-> Discussion

$\newcommand{\W}[1]{ \; #1 \; } \newcommand{\R}[1]{ {\rm #1} } \newcommand{\B}[1]{ {\bf #1} } \newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} } \newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} } \newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} } \newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }$
Atomic Operations and Multiple-Levels of AD: Example and Test

Discussion
One can use checkpoint or atomic_base to code an AD<Base> operation as atomic. This means that derivative computations that use the type Base will call the corresponding atomic_base member functions. On the other hand, if Base is AD<Other> the operations recorded at the Base level will not be atomic. This is demonstrated in this example.  # include <cppad/cppad.hpp> namespace { using CppAD::AD; typedef AD<double> a1double; typedef AD<a1double> a2double; typedef CPPAD_TESTVECTOR(a1double) a1vector; typedef CPPAD_TESTVECTOR(a2double) a2vector; void f_algo(const a2vector& x, a2vector& y) { size_t n = x.size(); y[0] = 0.0; for(size_t j = 1; j < n; j++) y[0] += x[j-1] * x[j]; return; } } // bool mul_level(void) { bool ok = true; using CppAD::checkpoint; using CppAD::ADFun; using CppAD::Independent; // domain dimension for this problem size_t n = 10; size_t m = 1; // checkpoint version of the function F(x) a2vector a2x(n), a2y(m); for(size_t j = 0; j < n; j++) a2x[j] = a2double(j + 1); // // could also use bool_sparsity_enum or set_sparsity_enum checkpoint<a1double> atom_f("atom_f", f_algo, a2x, a2y); // // Record a version of y = f(x) without checkpointing Independent(a2x); f_algo(a2x, a2y); ADFun<a1double> check_not(a2x, a2y); // // number of variables in a tape of f_algo that does not use checkpointing size_t size_not = check_not.size_var(); // // Record a version of y = f(x) with checkpointing Independent(a2x); atom_f(a2x, a2y); ADFun<a1double> check_yes(a2x, a2y); // // f_algo is represented by one atomic operation in this tape ok &= check_yes.size_var() < size_not; // // now record operations at a1double level a1vector a1x(n), a1y(m); for(size_t j = 0; j < n; j++) a1x[j] = a1double(j + 1); // // without checkpointing Independent(a1x); a1y = check_not.Forward(0, a1x); ADFun<double> with_not(a1x, a1y); // // should have the same size ok &= with_not.size_var() == size_not; // // with checkpointing Independent(a1x); a1y = check_yes.Forward(0, a1x); ADFun<double> with_yes(a1x, a1y); // // f_algo is nolonger represented by one atomic operation in this tape ok &= with_yes.size_var() == size_not; // return ok; } 
Input File: example/atomic/mul_level.cpp