\(\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}} }\)
mul_level¶
View page sourceUsing 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:
The function defining the differential equation could be calculated using the class
AD< AD<double> >
.The operations during the calculation of Taylor’s method could be done using the
AD<double>
class.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
( a2x , a2y )
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
( a1x , a1y )
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.