A Stiff Ode: Example and Test
Keywords: stiff ode: example test ode

| Prev | Next |  |  |  |  |  | ode_stiff.cpp | Headings

A Stiff Ode: Example and Test
Define x : R → R 2 by x 0 ( 0 ) = 1 x 1 ( 0 ) = 0 x 0 ′ ( t ) = - a 0 x 0 ( t ) x 1 ′ ( t ) = + a 0 x 0 ( t ) - a 1 x 1 ( t ) If a 0 ≫ a 1 > 0 , this is a stiff Ode and the analytic solution is x 0 ( t ) = exp ( - a 0 t ) x 1 ( t ) = a 0 [ exp ( - a 1 t ) - exp ( - a 0 t ) ] / ( a 0 - a 1 ) The example tests Rosen34 using the relations above: `

    # include <cppad/cppad.hpp>

    // To print the comparision, change the 0 to 1 on the next line.
    # define CPPAD_ODE_STIFF_PRINT 0

    namespace {
    	// --------------------------------------------------------------
    	class Fun {
    	private:
    		CPPAD_TESTVECTOR(double) a;
    	public:
    		// constructor
    		Fun(const CPPAD_TESTVECTOR(double)& a_) : a(a_)
    		{ }
    		// compute f(t, x)
    		void Ode(
    			const double                    &t,
    			const CPPAD_TESTVECTOR(double) &x,
    			CPPAD_TESTVECTOR(double)       &f)
    		{	f[0]  = - a[0] * x[0];
    			f[1]  = + a[0] * x[0] - a[1] * x[1];
    		}
    		// compute partial of f(t, x) w.r.t. t
    		void Ode_ind(
    			const double                    &t,
    			const CPPAD_TESTVECTOR(double) &x,
    			CPPAD_TESTVECTOR(double)       &f_t)
    		{	f_t[0] = 0.;
    			f_t[1] = 0.;
    		}
    		// compute partial of f(t, x) w.r.t. x
    		void Ode_dep(
    			const double                    &t,
    			const CPPAD_TESTVECTOR(double) &x,
    			CPPAD_TESTVECTOR(double)       &f_x)
    		{	f_x[0] = -a[0];
    			f_x[1] = 0.;
    			f_x[2] = +a[0];
    			f_x[3] = -a[1];
    		}
    	};
    	// --------------------------------------------------------------
    	class RungeMethod {
    	private:
    		Fun F;
    	public:
    		// constructor
    		RungeMethod(const CPPAD_TESTVECTOR(double) &a_) : F(a_)
    		{ }
    		void step(
    			double                     ta ,
    			double                     tb ,
    			CPPAD_TESTVECTOR(double) &xa ,
    			CPPAD_TESTVECTOR(double) &xb ,
    			CPPAD_TESTVECTOR(double) &eb )
    		{	xb = CppAD::Runge45(F, 1, ta, tb, xa, eb);
    		}
    		size_t order(void)
    		{	return 5; }
    	};
    	class RosenMethod {
    	private:
    		Fun F;
    	public:
    		// constructor
    		RosenMethod(const CPPAD_TESTVECTOR(double) &a_) : F(a_)
    		{ }
    		void step(
    			double                     ta ,
    			double                     tb ,
    			CPPAD_TESTVECTOR(double) &xa ,
    			CPPAD_TESTVECTOR(double) &xb ,
    			CPPAD_TESTVECTOR(double) &eb )
    		{	xb = CppAD::Rosen34(F, 1, ta, tb, xa, eb);
    		}
    		size_t order(void)
    		{	return 4; }
    	};
    }

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

    	CPPAD_TESTVECTOR(double) a(2);
    	a[0] = 1e3;
    	a[1] = 1.;
    	RosenMethod rosen(a);
    	RungeMethod runge(a);
    	Fun          gear(a);

    	CPPAD_TESTVECTOR(double) xi(2);
    	xi[0] = 1.;
    	xi[1] = 0.;

    	CPPAD_TESTVECTOR(double) eabs(2);
    	eabs[0] = 1e-6;
    	eabs[1] = 1e-6;

    	CPPAD_TESTVECTOR(double) ef(2);
    	CPPAD_TESTVECTOR(double) xf(2);
    	CPPAD_TESTVECTOR(double) maxabs(2);
    	size_t                nstep;

    	size_t k;
    	for(k = 0; k < 3; k++)
    	{
    		size_t M    = 5;
    		double ti   = 0.;
    		double tf   = 1.;
    		double smin = 1e-7;
    		double sini = 1e-7;
    		double smax = 1.;
    		double scur = .5;
    		double erel = 0.;

    		if( k == 0 )
    		{	xf = CppAD::OdeErrControl(rosen, ti, tf,
    			xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep);
    		}
    		else if( k == 1 )
    		{	xf = CppAD::OdeErrControl(runge, ti, tf,
    			xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep);
    		}
    		else if( k == 2 )
    		{	xf = CppAD::OdeGearControl(gear, M, ti, tf,
    			xi, smin, smax, sini, eabs, erel, ef, maxabs, nstep);
    		}
    		double x0 = exp(-a[0]*tf);
    		ok &= CppAD::NearEqual(x0, xf[0], 0., eabs[0]);
    		ok &= CppAD::NearEqual(0., ef[0], 0., eabs[0]);

    		double x1 = a[0] *
    			(exp(-a[1]*tf) - exp(-a[0]*tf))/(a[0] - a[1]);
    		ok &= CppAD::NearEqual(x1, xf[1], 0., eabs[1]);
    		ok &= CppAD::NearEqual(0., ef[1], 0., eabs[0]);
    # if CPPAD_ODE_STIFF_PRINT
    		const char* method[]={ "Rosen34", "Runge45", "Gear5" };
    		std::cout << std::endl;
    		std::cout << "method     = " << method[k] << std::endl;
    		std::cout << "nstep      = " << nstep  << std::endl;
    		std::cout << "x0         = " << x0 << std::endl;
    		std::cout << "xf[0]      = " << xf[0] << std::endl;
    		std::cout << "x0 - xf[0] = " << x0 - xf[0] << std::endl;
    		std::cout << "ef[0]      = " << ef[0] << std::endl;
    		std::cout << "x1         = " << x1 << std::endl;
    		std::cout << "xf[1]      = " << xf[1] << std::endl;
    		std::cout << "x1 - xf[1] = " << x1 - xf[1] << std::endl;
    		std::cout << "ef[1]      = " << ef[1] << std::endl;
    # endif
    	}

    	return ok;
    }

`

Input File: example/ode_stiff.cpp