template<typename Number>
void solve2(const Number* A, const Number* b, Number* x) {
Number det = A[0] * A[3] - A[1] * A[2];
x[0] = (A[3] * b[0] - A[1] * b[1]) / det;
x[1] = (-A[2] * b[0] + A[0] * b[1]) / det;
}
#include <codi.hpp>
#include <iostream>
template<typename Number>
void solve2(const Number* A, const Number* b, Number* x) {
Number det = A[0] * A[3] - A[1] * A[2];
x[0] = (A[3] * b[0] - A[1] * b[1]) / det;
x[1] = (-A[2] * b[0] + A[0] * b[1]) / det;
}
solve2(&x[0], &x[4], y);
}
BaseReal ATrans[4] = {x[0], x[2], x[1], x[3]};
BaseReal s[2];
solve2(ATrans, y_b, s);
x_b[0] = -s[0] * y[0];
x_b[1] = -s[0] * y[1];
x_b[2] = -s[1] * y[0];
x_b[3] = -s[1] * y[1];
x_b[4] = s[0];
x_b[5] = s[1];
}
void runExample(int mode) {
tape.setActive();
tape.registerInput(u);
Real A[4] = { u * 1.0, 0.5, 0.25, u * -1.0};
Real b[2] = {u * 10.0, u * 20.0};
if(1 == mode) {
std::cout << "Running regular differentiation without external functions." << std::endl;
solve2(A, b, x);
} else if(2 == mode) {
std::cout << "Running differentiation with external function, primal is called via a special function implementation." << std::endl;
for(int i = 0; i < 4; ++i) {
}
for(int i = 0; i < 2; ++i) {
}
for(int i = 0; i < 2; ++i) {
}
} else if(3 == mode) {
std::cout << "Running differentiation with external function, primal is called via a passive AD evaluation." << std::endl;
for(int i = 0; i < 4; ++i) {
}
for(int i = 0; i < 2; ++i) {
}
for(int i = 0; i < 2; ++i) {
}
} else {
std::cerr << "Error: Unknown mode '" << mode << "'." << std::endl;
}
Real w = sqrt(x[0] * x[0] + x[1] * x[1]);
tape.registerOutput(w);
tape.setPassive();
tape.evaluate();
std::cout << "Solution w: " << w << std::endl;
std::cout <<
"Adjoint u: " << u.
getGradient() << std::endl;
tape.reset();
}
int main(int nargs, char** args) {
runExample(1);
runExample(2);
runExample(3);
return 0;
}
RealReverseGen< double > RealReverse
Definition: codi.hpp:120
Represents a concrete lvalue in the CoDiPack expression tree.
Definition: activeType.hpp:52
static Tape & getTape()
Get a reference to the tape which manages this expression.
Definition: activeType.hpp:99
T_Tape Tape
See ActiveType.
Definition: activeType.hpp:55
typename Tape::Real Real
See LhsExpressionInterface.
Definition: activeTypeBase.hpp:76
Helper class for the implementation of an external function in CoDiPack.
Definition: externalFunctionHelper.hpp:102
void addInput(Type const &input)
Add an input value.
Definition: externalFunctionHelper.hpp:451
void callPrimalFuncWithADType(FuncObj &func, Args &&... args)
Definition: externalFunctionHelper.hpp:513
void addOutput(Type &output)
Add an output value.
Definition: externalFunctionHelper.hpp:492
void callPrimalFunc(PrimalFunc func)
Definition: externalFunctionHelper.hpp:539
void addToTape(ReverseFunc reverseFunc, ForwardFunc forwardFunc=nullptr, PrimalFunc primalFunc=nullptr)
Add the external function to the tape.
Definition: externalFunctionHelper.hpp:577
Ease of access structure for user-provided data on the tape for external functions....
Definition: externalFunctionUserData.hpp:59
void setGradient(Gradient const &g)
Set the gradient of this lvalue in the tape.
Definition: lhsExpressionInterface.hpp:120
Gradient getGradient() const
Get the gradient of this lvalue from the tape.
Definition: lhsExpressionInterface.hpp:115
The steps for using the codi::ExternalFUnctionHelper are then quite simple. The user has to:
For the fourth step the user has two choices. Either a primal evaluation function with the header PrimalFunc can be implemented or the original function can be evaluated with the CoDiPack type. In the second option nothing is recorded during this evaluation.
After the function is registered on the tape, the helper is reset so that it can be used to push another external function.