Prev
Next
Index->
contents
reference
index
search
external
Up->
CppAD
AD
ADValued
atomic
atomic_four
atomic_four_example
atomic_four_lin_ode
atomic_four_lin_ode_implement
atomic_four_lin_ode_forward.hpp
atomic_four_lin_ode_forward.hpp
Headings->
Purpose
Theory
extend_ode
Source
@(@\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
.
Atomic Linear ODE Forward Mode: Example Implementation
Purpose
The forward
routine overrides the virtual functions
used by the atomic_four base; see
forward
.
Theory
Suppose we are given Taylor coefficients
@(@
x^0
@)@ , @(@
x^1
@)@ , for
x
.
The zero order Taylor coefficient for
z(t, x)
solves
the following initial value ODE:
@[@
z_t^0 (t) = A^0 z(t) \W{,} z^0 (0) = b^0
@]@
Note that @(@
A^0
@)@ and @(@
b^0
@)@
are just certain components of @(@
x^0
@)@ ; see
A(x)
and
b(x)
.
The first order Taylor coefficient for @(@
z(t, x)
@)@ solves
the following initial value ODE:
@[@
z_t^1 (t)
=
A^0 z^1 (t) + A^1 z^0 (t) \W{,} z^1 (0) = b^1
@]@
Note that @(@
A^1
@)@ and @(@
c^1
@)@
are just certain components of @(@
x^1
@)@ .
We can solve for @(@
z^1 (t)
@)@ using the following extended
initial value ODE:
@[@
\left[ \begin{array}{c}
z^0_t (t, x) \\
z^1_t (t, x)
\end{array} \right]
=
\left[ \begin{array}{cc}
A^0 & 0 \\
A^1 & A^0
\end{array} \right]
\left[ \begin{array}{c}
z^0 (t, x) \\
z^1 (t, x)
\end{array} \right]
\; , \;
\left[ \begin{array}{c}
z^0 (0, x) \\
z^1 (0, x)
\end{array} \right]
=
\left[ \begin{array}{c}
b^0 \\
b^1
\end{array} \right]
@]@
extend_ode
The extended system above is created form the original system by the
extend_ode
function defined below:
Source
# include <cppad/example/atomic_four/lin_ode/lin_ode.hpp>
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
// ----------------------------------------------------------------------------
// forward override for Base atomic linear ODE
template < class Base >
bool atomic_lin_ode< Base>:: forward (
size_t call_id ,
const CppAD:: vector< bool >& select_y ,
size_t order_low ,
size_t order_up ,
const CppAD:: vector< Base>& taylor_x ,
CppAD:: vector< Base>& taylor_y )
{
// order_up
if ( order_up > 1 )
return false ;
//
// r, pattern, transpose, nnz
Base r;
Base step;
sparse_rc pattern;
bool transpose;
get ( call_id, r, step, pattern, transpose);
# ifndef NDEBUG
size_t nnz = pattern. nnz ();
# endif
//
// q
size_t q = order_up + 1 ;
//
// m
CPPAD_ASSERT_UNKNOWN ( taylor_y. size () % q == 0 );
size_t m = taylor_y. size () / q;
CPPAD_ASSERT_UNKNOWN ( pattern. nr () == m );
CPPAD_ASSERT_UNKNOWN ( pattern. nc () == m );
//
// taylor_x
CPPAD_ASSERT_UNKNOWN ( taylor_x. size () == ( nnz + m) * q );
//
// taylor_y
if ( order_up == 0 )
base_solver ( r, step, pattern, transpose, taylor_x, taylor_y);
else
{ CPPAD_ASSERT_UNKNOWN ( order_up == 1 );
//
// pattern_extend, x_extend
sparse_rc pattern_extend;
CppAD:: vector<Base> x_extend;
extend_ode ( pattern, transpose, taylor_x, pattern_extend, x_extend);
//
// y_extend
size_t m_extend = pattern_extend. nr ();
CppAD:: vector<Base> y_extend ( m_extend);
bool transpose_extend = false ;
base_solver (
r, step, pattern_extend, transpose_extend, x_extend, y_extend
);
//
// taylor_y
if ( order_low == 0 )
{ for ( size_t i = 0 ; i < m; ++ i)
taylor_y[ i * q + 0 ] = y_extend[ i];
}
for ( size_t i = 0 ; i < m; ++ i)
taylor_y[ i * q + 1 ] = y_extend[ m + i];
}
//
return true ;
}
// ----------------------------------------------------------------------------
// forward override for AD<Base> atomic linear ODE
template < class Base >
bool atomic_lin_ode< Base>:: forward (
size_t call_id ,
const CppAD:: vector< bool >& select_y ,
size_t order_low ,
size_t order_up ,
const CppAD:: vector< CppAD:: AD< Base> >& ataylor_x ,
CppAD:: vector< CppAD:: AD< Base> >& ataylor_y )
{ //
// ad_base
typedef CppAD:: AD<Base> ad_base;
//
// order_up
if ( order_up > 1 )
return false ;
//
// r, pattern, transpose, nnz
Base r;
Base step;
sparse_rc pattern;
bool transpose;
get ( call_id, r, step, pattern, transpose);
# ifndef NDEBUG
size_t nnz = pattern. nnz ();
# endif
//
// q
size_t q = order_up + 1 ;
//
// m
CPPAD_ASSERT_UNKNOWN ( ataylor_y. size () % q == 0 );
size_t m = ataylor_y. size () / q;
//
// ataylor_x
CPPAD_ASSERT_UNKNOWN ( ataylor_x. size () == ( nnz + m) * q );
//
// ataylor_y
if ( order_up == 0 )
(* this )( call_id, ataylor_x, ataylor_y);
else
{ CPPAD_ASSERT_UNKNOWN ( order_up == 1 );
//
// pattern_extend, x_extend
sparse_rc pattern_extend;
CppAD:: vector<ad_base> ax_extend;
extend_ode ( pattern, transpose, ataylor_x, pattern_extend, ax_extend);
//
// call_id_2
bool transpose_extend = false ;
size_t call_id_2 = set ( r, step, pattern_extend, transpose_extend);
//
// ay_extend
size_t m_extend = pattern_extend. nr ();
CppAD:: vector<ad_base> ay_extend ( m_extend);
(* this )( call_id_2, ax_extend, ay_extend);
//
// ataylor_y
if ( order_low == 0 )
{ for ( size_t i = 0 ; i < m; ++ i)
ataylor_y[ i * q + 0 ] = ay_extend[ i];
}
for ( size_t i = 0 ; i < m; ++ i)
ataylor_y[ i * q + 1 ] = ay_extend[ m + i];
}
//
return true ;
}
// ---------------------------------------------------------------------------
// extend_ode
/*
[ z_t^0 (t, x^0 ) ] = [ A^0 0 ] * [ z^0 (t, x^0 ) ]
[ z_t^1 (t, x^0, x^1 ) ] [ A^1 A^0 ] [ z^1 (t, x^0, x^1 ) ]
[ z^0 (0, x^0 ) ] = [ b^0 ]
[ z^1 (0, x^0, x^1 ) ] [ b^1 ]
*/
template < class Base >
template < class Float >
void atomic_lin_ode< Base>:: extend_ode (
const CppAD:: sparse_rc< CppAD:: vector< size_t> >& pattern ,
const bool & transpose ,
const CppAD:: vector< Float>& taylor_x ,
CppAD:: sparse_rc< CppAD:: vector< size_t> >& pattern_extend ,
CppAD:: vector< Float>& x_extend )
{ //
// m
size_t m = pattern. nr ();
size_t nnz = pattern. nnz ();
CPPAD_ASSERT_UNKNOWN ( pattern. nc () == m );
//
// q
size_t q = 2 ;
CPPAD_ASSERT_UNKNOWN ( taylor_x. size () == q * ( nnz + m) );
//
// m_extend
size_t m_extend = 2 * m;
size_t nnz_extend = 3 * nnz;
//
// pattern_extend, x_extend
pattern_extend. resize ( m_extend, m_extend, nnz_extend);
x_extend. resize ( nnz_extend + m_extend);
for ( size_t k = 0 ; k < nnz; ++ k)
{ size_t i = pattern. row ()[ k];
size_t j = pattern. col ()[ k];
if ( transpose )
std:: swap ( i, j);
//
// A^0_ij
Float A0ij = taylor_x[ k * q + 0 ];
//
// A^1_ij
Float A1ij = taylor_x[ k * q + 1 ];
//
// upper diagonal
pattern_extend. set ( 3 * k + 0 , i, j);
x_extend[ 3 * k + 0 ] = A0ij;
//
// lower left
pattern_extend. set ( 3 * k + 1 , m + i, j);
x_extend[ 3 * k + 1 ] = A1ij;
//
// lower diagonal
pattern_extend. set ( 3 * k + 2 , m + i, m + j);
x_extend[ 3 * k + 2 ] = A0ij;
}
for ( size_t i = 0 ; i < m; ++ i)
{ // b^0_i
x_extend[ nnz_extend + i] = taylor_x[ ( nnz + i) * q + 0 ];
// b^1_i
x_extend[ nnz_extend + m + i] = taylor_x[ ( nnz + i) * q + 1 ];
}
return ;
}
} // END_CPPAD_NAMESPACE
Input File: include/cppad/example/atomic_four/lin_ode/forward.hpp