Goal: Introduction to reverse mode AD with CoDiPack.
Prerequisite: AD reverse mode. See Reverse AD Equation
Function: Simple real valued function
Full code:
The derivative computation with the reverse mode of CoDiPack needs in total nine steps:
Most of these steps need to call functions on the global tape structure of CoDiPack. This structure can be accessed with the function getTape.
For this step, it is sufficient to call the method setActive. This will enable the recording in CoDiPack for all statements evaluated after the setActive
call.
In the reverse AD equation, the variable describes the vector of input variables. CoDiPack needs to know about all these values. On each one, the method registerInput needs to be called.
In this step, CoDiPack is only indirectly involved. The function needs to be evaluated in the program and CoDiPack needs to record the statements that are called during the evaluation. It is therefore necessary to write the function such that it uses the CoDiPack type. How this is done depends on the program that is differentiated. The best option is to write the function as a template function such that the calculation type is flexible. The second option is most of the time used when software with a large code base is differentiated. Here, a global typedef like using Real = codi::RealReverse
is used and all doubles in the program are changed to this typedef. The calculation type can then be changed during compile time and different executables can be generated.
In the reverse AD equation, the variable describes the vector of output variables. CoDiPack needs to know about all these values. On each one, the method registerOutput needs to be called.
For this step it is sufficient to call the method setPassive. This will disable the recording in CoDiPack for all statements evaluated after the setPassive
call.
In the reverse AD equation, the variable is the vector of adjoint output variables. Since these variables serve in the reverse mode of AD as inputs, they need to be defined before the reverse evaluation is started. The ''bar'' values of the variables can be accessed via the functions gradient and setGradient. The default value is zero for the gradients.
For an access to the gradient data for variables which run out of scope, see Direct data access (Identifier management).
The simplest way to evaluate the full tape is to call the method evaluate. This will evaluate the full tape from the last recorded statement to the first one.
For a partial evaluation of the tape see Example 3 - Positional tape evaluations. There are also other evaluation possibilities available, which are described in other Tutorials.
In the reverse AD equation, the variable is the vector of adjoint input variables. After an evaluation of the tape, these values are populated with the derivative data. The ''bar'' values of the variables can be accessed via the functions gradient and getGradient.
CoDiPack will clear these values only when the tape is reset or the adjoints are cleared. If these calls are forgotten and multiples evaluations are performed, then the derivative data will be accumulated.
The last step is very important when multiple tape evaluations or recordings are performed during one program execution. A tape can be reset via the function reset.
Depending on the use case, a full tape reset might not be necessary. See Tutorial 3 - Full Jacobian computation (Multiple reverse evaluations) and Tutorial 5 - Repeated tape recordings for more details.