Prev Next ode_err_maxabs.cpp Headings

@(@\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}} }@)@This is cppad-20221105 documentation. Here is a link to its current documentation .
OdeErrControl: Example and Test Using Maxabs Argument
Define @(@ X : \B{R} \rightarrow \B{R}^2 @)@ by @[@ \begin{array}{rcl} X_0 (t) & = & - \exp ( - w_0 t ) \\ X_1 (t) & = & \frac{w_0}{w_1 - w_0} [ \exp ( - w_0 t ) - \exp( - w_1 t )] \end{array} @]@ It follows that @(@ X_0 (0) = 1 @)@, @(@ X_1 (0) = 0 @)@ and @[@ \begin{array}{rcl} X_0^{(1)} (t) & = & - w_0 X_0 (t) \\ X_1^{(1)} (t) & = & + w_0 X_0 (t) - w_1 X_1 (t) \end{array} @]@ Note that @(@ X_1 (0) @)@ is zero an if @(@ w_0 t @)@ is large, @(@ X_0 (t) @)@ is near zero. This example tests OdeErrControl using the maxabs argument.

# include <cstddef>              // for size_t
# include <cmath>                // for exp
# include <cppad/utility/ode_err_control.hpp>   // CppAD::OdeErrControl
# include <cppad/utility/near_equal.hpp>    // CppAD::NearEqual
# include <cppad/utility/vector.hpp> // CppAD::vector
# include <cppad/utility/runge_45.hpp>      // CppAD::Runge45

namespace {
    // --------------------------------------------------------------
    class Fun {
    private:
         CppAD::vector<double> w;
    public:
        // constructor
        Fun(const CppAD::vector<double> &w_) : w(w_)
        { }

        // set f = x'(t)
        void Ode(
            const double                &t,
            const CppAD::vector<double> &x,
            CppAD::vector<double>       &f)
        {   f[0] = - w[0] * x[0];
            f[1] = + w[0] * x[0] - w[1] * x[1];
        }
    };

    // --------------------------------------------------------------
    class Method {
    private:
        Fun F;
    public:
        // constructor
        Method(const CppAD::vector<double> &w_) : F(w_)
        { }
        void step(
            double ta,
            double tb,
            CppAD::vector<double> &xa ,
            CppAD::vector<double> &xb ,
            CppAD::vector<double> &eb )
        {   xb = CppAD::Runge45(F, 1, ta, tb, xa, eb);
        }
        size_t order(void)
        {   return 4; }
    };
}

bool OdeErrMaxabs(void)
{   bool ok = true;     // initial return value

    CppAD::vector<double> w(2);
    w[0] = 10.;
    w[1] = 1.;
    Method method(w);

    CppAD::vector<double> xi(2);
    xi[0] = 1.;
    xi[1] = 0.;

    CppAD::vector<double> eabs(2);
    eabs[0] = 0.;
    eabs[1] = 0.;

    CppAD::vector<double> ef(2);
    CppAD::vector<double> xf(2);
    CppAD::vector<double> maxabs(2);

    double ti   = 0.;
    double tf   = 1.;
    double smin = .5;
    double smax = 1.;
    double scur = .5;
    double erel = 1e-4;

    bool accurate = false;
    while( ! accurate )
    {   xf = OdeErrControl(method,
            ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs);
        accurate = true;
        size_t i;
        for(i = 0; i < 2; i++)
            accurate &= ef[i] <= erel * maxabs[i];
        if( ! accurate )
            smin = smin / 2;
    }

    double x0 = exp(-w[0]*tf);
    ok &= CppAD::NearEqual(x0, xf[0], erel, 0.);
    ok &= CppAD::NearEqual(0., ef[0], erel, erel);

    double x1 = w[0] * (exp(-w[0]*tf) - exp(-w[1]*tf))/(w[1] - w[0]);
    ok &= CppAD::NearEqual(x1, xf[1], erel, 0.);
    ok &= CppAD::NearEqual(0., ef[1], erel, erel);

    return ok;
}

Input File: example/utility/ode_err_maxabs.cpp