Prev Next

@(@\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}} }@)@This is cppad-20221105 documentation. Here is a link to its current documentation .
Using Multiple Levels of AD

Alternative
Often it is easier to use base2ad and dynamic parameters to accomplish the objective below.

Background
If f is an ADFun<Base> object, the vectors returned by f.Forward , and f.Reverse , have values of type Base and not AD<Base> . This reflects the fact that operations used to calculate these function values are not recorded by the tape corresponding to AD<Base> operations.

Motivation
Suppose that you use derivatives of one or more inner functions as part of the operations needed to compute an outer function. For example, the derivatives returned by f.Forward might be used as part of Taylor's method for solving ordinary differential equations. In addition, we might want to differentiate the solution of a differential equation with respect to parameters in the equation. This can be accomplished in the following way:
  1. The function defining the differential equation could be calculated using the class AD< AD<double> > .
  2. The operations during the calculation of Taylor's method could be done using the AD<double> class.
  3. Derivatives of the solution of the differential equation could then be calculated using the double class.


Procedure

First Start AD<double>
If some of the parameters in the AD< AD<double> > recording depend on the variables in the AD<double> recording, we must first declaring these variables; i.e.,
    Independent(
a1x)
where a1x is a SimpleVector with elements of type AD<double> . This will start recording a new tape of operations performed using AD<double> class objects.

Start AD< AD<double> > Recording
The next step is to declare the independent variables using
    Independent(
a2x)
where a2x is a SimpleVector with elements of type AD< AD<double> > . This will start recording a new tape of operations performed using AD< AD<double> > class objects.

Inner Function
The next step is to calculate the inner function using AD< AD<double> > class objects. We then stop the recording using
    
a1f.Dependent(a2xa2y)
where a2y is a SimpleVector with elements of type AD< AD<double> > and a1f is an ADFun< AD<double> > object.

Second Start AD< AD<double> >
If none of the parameters in the AD< AD<double> > recording depend on the variables in the AD<double> recording, it is preferred to delay declaring these variables to this point; i.e.,
    Independent(
a1x)
where a1x is a SimpleVector with elements of type AD<double> . This will start recording a new tape of operations performed using AD<double> class objects.

Outer Function
The next step is to calculate the outer function using AD<double> class objects. Note that derivatives of the inner function can be included in the calculation of the outer function using a1f . We then stop the recording of AD<double> operations using
    
g.Dependent(a1xa1y)
where a1y is a SimpleVector with elements of type AD<double> and g is an ADFun<double> object.

Derivatives of Outer Function
The AD function object g can then be used to calculate the derivatives of the outer function.

Example
The files mul_level.cpp and change_param.cpp contain an examples and tests of this procedure. They return true if they succeed and false otherwise. The file mul_level_ode.cpp is a more complex example use of multiple tapes.
Input File: omh/mul_level.omh