|
Prev
| Next
|
|
|
|
|
|
ode_stiff.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
.
A Stiff Ode: Example and Test
Define
@(@
x : \B{R} \rightarrow \B{R}^2
@)@ by
@[@
\begin{array}{rcl}
x_0 (0) & = & 1 \\
x_1 (0) & = & 0 \\
x_0^\prime (t) & = & - a_0 x_0 (t) \\
x_1^\prime (t) & = & + a_0 x_0 (t) - a_1 x_1 (t)
\end{array}
@]@
If @(@
a_0 \gg a_1 > 0
@)@, this is a stiff Ode and
the analytic solution is
@[@
\begin{array}{rcl}
x_0 (t) & = & \exp( - a_0 t ) \\
x_1 (t) & = & a_0 [ \exp( - a_1 t ) - \exp( - a_0 t ) ] / ( a_0 - a_1 )
\end{array}
@]@
The example tests Rosen34 using the relations above:
# include <cppad/cppad.hpp>
// To print the comparison, 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/general/ode_stiff.cpp