/* nag::ad::f07ca Tangent over Tangent Example Program.
*/
#include <dco.hpp>
#include <iostream>
#include <nagad.h>
// Function which calls NAG AD Library routines.
template <typename T>
void func(std::vector<T> &l,
std::vector<T> &d,
std::vector<T> &u,
std::vector<T> &x);
// Driver with the tangent calls.
// Computes the solution to a system of linear equations Ax=b where A is a
// triagonal matrix of size n. Matrix A is stored in arrays l(n-1), d(n), u(n-1)
// that store the lower, the main and the upper diagonals. Also, computes the
// sum of the Hessian elements of output x w.r.t. all inputs l, d, u, b.
void driver(const std::vector<double> &lv,
const std::vector<double> &dv,
const std::vector<double> &uv,
const std::vector<double> &bv,
std::vector<double> & xv,
double & d2xdall2);
int main()
{
std::cout << " nag::ad::f07ca Tangent over Tangent Example Program Results\n";
// Problem dimension
Integer n = 5;
// Matrix A stored in diagonals
std::vector<double> lv = {3.4, 3.6, 7.0, -6.0};
std::vector<double> dv = {3.0, 2.3, -5.0, -0.9, 7.1};
std::vector<double> uv = {2.1, -1.0, 1.9, 8.0};
// Right-hand-side vector b
std::vector<double> bv = {2.7, -0.5, 2.6, 0.6, 2.7};
// Computed solution to the system Ax=b
std::vector<double> xv(n);
double dx2_dall2;
// Call driver
driver(lv, dv, uv, bv, xv, dx2_dall2);
std::cout << "\n Solution point = ";
for (int i = 0; i < n; i++)
{
std::cout.width(5);
std::cout << xv[i];
}
std::cout << std::endl;
std::cout.setf(std::ios::scientific, std::ios::floatfield);
std::cout.precision(12);
std::cout << "\n Derivatives calculated: Second order tangents\n";
std::cout
<< "\n Sum of all Hessian elements of solution x w.r.t. l,d,u and b:\n";
std::cout << " sum_ij [d2x/dall2]_ij = " << dx2_dall2 << std::endl;
return 0;
}
// Driver with the tangents calls.
// Computes the solution to a system of linear equations Ax=b where A is a
// triagonal matrix of size n. Matrix A is stored in arrays l(n-1), d(n), u(n-1)
// that store the lower, the main and the upper diagonals. Also, computes the
// sum of the Hessian elements of output x w.r.t. all inputs l, d, u, b.
void driver(const std::vector<double> &lv,
const std::vector<double> &dv,
const std::vector<double> &uv,
const std::vector<double> &bv,
std::vector<double> & xv,
double & dx2_dall2)
{
using T = dco::gt1s<dco::gt1s<double>::type>::type;
Integer n = xv.size();
Integer n1 = n - 1;
// Stores the lower diagonal of A
std::vector<T> l(n1);
dco::passive_value(l) = lv;
dco::derivative(dco::value(l)) = std::vector<double>(n1, 1.0);
dco::value(dco::derivative(l)) = std::vector<double>(n1, 1.0);
// Stores the main diagonal of A
std::vector<T> d(n);
dco::passive_value(d) = dv;
dco::derivative(dco::value(d)) = std::vector<double>(n, 1.0);
dco::value(dco::derivative(d)) = std::vector<double>(n, 1.0);
// Stores the upper diagonal of A
std::vector<T> u(n1);
dco::passive_value(u) = uv;
dco::derivative(dco::value(u)) = std::vector<double>(n1, 1.0);
dco::value(dco::derivative(u)) = std::vector<double>(n1, 1.0);
// Stores right-hand-side vector b
std::vector<T> b(n);
dco::passive_value(b) = bv;
dco::derivative(dco::value(b)) = std::vector<double>(n, 1.0);
dco::value(dco::derivative(b)) = std::vector<double>(n, 1.0);
// nag::ad::f07ca modifies rhs b and returns solution x into the same array
// Tangent mode is unaffected.
std::vector<T> &x = b;
// Call the NAG AD Lib functions
func(l, d, u, x);
// Solution point
xv = dco::passive_value(x);
// Get sum of Hessian elements of solution x w.r.t. b
dx2_dall2 = 0;
for (int i = 0; i < n; i++)
{
dx2_dall2 += dco::derivative(dco::derivative(x[i]));
}
}
// Function which calls NAG AD Library routines.
template <typename T>
void func(std::vector<T> &l,
std::vector<T> &d,
std::vector<T> &u,
std::vector<T> &x)
{
Integer n = x.size(), nrhs = 1;
// Create AD configuration data object
Integer ifail = 0;
nag::ad::handle_t ad_handle;
// Solve the equations Ax = b for x
ifail = 0;
nag::ad::f07ca(ad_handle, n, nrhs, l.data(), d.data(), u.data(), x.data(), n,
ifail);
ifail = 0;
}