Prev Next test_circle_implicit_newton Headings

@(@\newcommand{\B}[1]{{\bf #1}} \newcommand{\R}[1]{{\rm #1}}@)@
Example / Test of Implicit Newton Class
//
// simple implicit function y(x) defined by
// 0 = L(x, y) = x^2  + y(x)^2  - 1
//
class newton_circle {
public:
     newton_circle(void)
     { }
     VECTOR(double) function(const VECTOR(double)& x)
     {    assert( x.size() == 1 );
          VECTOR(double) y(1);
          y[0] = sqrt( 1.0 - x[0] * x[0] );
          return y;
     }
     template <class Scalar>
     VECTOR(Scalar) derivative(const VECTOR(Scalar)& x, const VECTOR(Scalar)& y)
     {    // b = L_y (x, y)
          VECTOR(Scalar) b(1);
          b[0] = 2.0 * y[0];
          return b;
     }
     VECTOR( CppAD::AD<double> ) linear(
          const VECTOR( CppAD::AD<double>)&   b ,
          const VECTOR( CppAD::AD<double>)&   v )
     {    VECTOR( CppAD::AD<double> ) u(1);
          assert( v.size() == 1 );
          u[0] = v[0] / b[0];
          return u;
     }
};
bool test_cricle_implicit_newton(void)
{    bool ok = true;
     double eps99 = 99.0 * std::numeric_limits<double>::epsilon();
     typedef CppAD::AD<double>   adouble;
     typedef CppAD::AD<adouble> a2double;

     // record z = L(x, y)
     VECTOR(a2double) a2xy(2), a2z(1);
     a2xy[0] = a2double( 0.5 );
     a2xy[1] = a2double( 0.5 );
     CppAD::Independent( a2xy );
     a2z[0] = a2xy[0] * a2xy[0] + a2xy[1] * a2xy[1] - 1.0;
     CppAD::ADFun<adouble> aL_fun(a2xy, a2z);

     // record F(x, y) = y
     VECTOR(adouble) axy(2), az(1);
     axy[0] = adouble( 0.5 );
     axy[1] = adouble( 0.5 );
     CppAD::Independent( axy );
     az[0] = axy[1];
     CppAD::ADFun<double> F_fun(axy, az);

     // solver used by newton_ad object
     newton_circle solve;

     // create implicit function object
     bool  full_step = false;
     size_t num_step = 2;
     implicit_newton<newton_circle> newton_ad(
          full_step, num_step, aL_fun, F_fun, solve
     );

     // Taylor coefficient vectors
     VECTOR(double) xk(1), yk(1);

     // zero order, y(t) = sqrt(1 - x(t) * x(t) )
     size_t k  = 0;
     double x0 = 0.5;
     xk[0]     = x0;
     yk        = newton_ad.Forward(k, xk);
     double y0 = sqrt(1.0 - x0 * x0);
     ok       &= CppAD::NearEqual(yk[0], y0, eps99, eps99);

     // differentiate zero order forward
     // y0 = sqrt( 1.0 - x0 * x0 )
     size_t q        = 1;
     VECTOR(double) w(q), dw(q);
     w[0]            = 1.0;
     dw              = newton_ad.Reverse(q, w);
     double dy0_dx0  = - x0 / y0;
     ok             &= CppAD::NearEqual(dw[0], dy0_dx0, eps99, eps99);

     // first order, y'(t) = - x(t) * x'(t) / sqrt(r0 - x(t) * x(t) )
     k         = 1;
     double x1 = 0.75;
     xk[0]     = x1;
     yk        = newton_ad.Forward(k, xk);
     double y1 = - x0 * x1 / y0;
     ok       &= CppAD::NearEqual(yk[0], y1, eps99, eps99);

     // differentiate first order forward
     // y1(x0, x1) = - x0 * x1 / y0
     q               = 2;
     w.resize(q);
     dw.resize(q);
     w[0]            = 0.0;
     w[1]            = 1.0;
     dw              = newton_ad.Reverse(q, w);
     double dy1_dx1  = - x0 / y0;
     ok           &= CppAD::NearEqual(dw[1], dy1_dx1, eps99, eps99);
     double dy1_dx0  = - x1 / y0 + ( x0 * x1 / (y0 * y0) ) * dy0_dx0;
     ok           &= CppAD::NearEqual(dw[0], dy1_dx0, eps99, eps99);

     // second order
     // y''(t) = - x'(t) * x'(t) / sqrt(r0 - x(t) * x(t) )
     //          - x(t) * x''(t) / sqrt(r0 - x(t) * x(t) )
     //          - (x(t) * x'(t))^2  / sqrt(r0 - x(t) * x(t) )^3
     k         = 2;
     double x2 = 0.25;
     xk[0]     = x2;
     yk        = newton_ad.Forward(k, xk);
     double y2 = - x1 * x1 / (2.0 * y0);
     y2       -= x0 * x2 / y0;
     y2       -= (x0 * x1) * (x0 * x1) / (2.0 * y0 * y0 * y0);
     ok       &= CppAD::NearEqual(yk[0], y2, eps99, eps99);
     //
     return ok;
}

Input File: src/implicit_newton.cpp