248 lines
8.3 KiB
Plaintext
248 lines
8.3 KiB
Plaintext
/*
|
|
[auto_generated]
|
|
boost/numeric/odeint/stepper/detail/generic_rk_algorithm.hpp
|
|
|
|
[begin_description]
|
|
Implementation of the generic Runge-Kutta method.
|
|
[end_description]
|
|
|
|
Copyright 2011-2013 Mario Mulansky
|
|
Copyright 2011-2012 Karsten Ahnert
|
|
Copyright 2012 Christoph Koke
|
|
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file LICENSE_1_0.txt or
|
|
copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
|
|
|
|
#ifndef BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_ALGORITHM_HPP_INCLUDED
|
|
#define BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_ALGORITHM_HPP_INCLUDED
|
|
|
|
#include <boost/static_assert.hpp>
|
|
|
|
#include <boost/mpl/vector.hpp>
|
|
#include <boost/mpl/push_back.hpp>
|
|
#include <boost/mpl/for_each.hpp>
|
|
#include <boost/mpl/range_c.hpp>
|
|
#include <boost/mpl/copy.hpp>
|
|
#include <boost/mpl/size_t.hpp>
|
|
|
|
#include <boost/fusion/algorithm.hpp>
|
|
#include <boost/fusion/iterator.hpp>
|
|
#include <boost/fusion/mpl.hpp>
|
|
#include <boost/fusion/sequence.hpp>
|
|
|
|
#include <boost/array.hpp>
|
|
|
|
#include <boost/numeric/odeint/algebra/range_algebra.hpp>
|
|
#include <boost/numeric/odeint/algebra/default_operations.hpp>
|
|
#include <boost/numeric/odeint/stepper/detail/generic_rk_call_algebra.hpp>
|
|
#include <boost/numeric/odeint/stepper/detail/generic_rk_operations.hpp>
|
|
#include <boost/numeric/odeint/util/bind.hpp>
|
|
|
|
namespace boost {
|
|
namespace numeric {
|
|
namespace odeint {
|
|
namespace detail {
|
|
|
|
template< class T , class Constant >
|
|
struct array_wrapper
|
|
{
|
|
typedef const typename boost::array< T , Constant::value > type;
|
|
};
|
|
|
|
template< class T , size_t i >
|
|
struct stage
|
|
{
|
|
T c;
|
|
boost::array< T , i > a;
|
|
};
|
|
|
|
|
|
template< class T , class Constant >
|
|
struct stage_wrapper
|
|
{
|
|
typedef stage< T , Constant::value > type;
|
|
};
|
|
|
|
|
|
template<
|
|
size_t StageCount,
|
|
class Value ,
|
|
class Algebra ,
|
|
class Operations
|
|
>
|
|
class generic_rk_algorithm {
|
|
|
|
public:
|
|
typedef mpl::range_c< size_t , 1 , StageCount > stage_indices;
|
|
|
|
typedef typename boost::fusion::result_of::as_vector
|
|
<
|
|
typename boost::mpl::copy
|
|
<
|
|
stage_indices ,
|
|
boost::mpl::inserter
|
|
<
|
|
boost::mpl::vector0< > ,
|
|
boost::mpl::push_back< boost::mpl::_1 , array_wrapper< Value , boost::mpl::_2 > >
|
|
>
|
|
>::type
|
|
>::type coef_a_type;
|
|
|
|
typedef boost::array< Value , StageCount > coef_b_type;
|
|
typedef boost::array< Value , StageCount > coef_c_type;
|
|
|
|
typedef typename boost::fusion::result_of::as_vector
|
|
<
|
|
typename boost::mpl::push_back
|
|
<
|
|
typename boost::mpl::copy
|
|
<
|
|
stage_indices,
|
|
boost::mpl::inserter
|
|
<
|
|
boost::mpl::vector0<> ,
|
|
boost::mpl::push_back< boost::mpl::_1 , stage_wrapper< Value , boost::mpl::_2 > >
|
|
>
|
|
>::type ,
|
|
stage< Value , StageCount >
|
|
>::type
|
|
>::type stage_vector_base;
|
|
|
|
|
|
struct stage_vector : public stage_vector_base
|
|
{
|
|
struct do_insertion
|
|
{
|
|
stage_vector_base &m_base;
|
|
const coef_a_type &m_a;
|
|
const coef_c_type &m_c;
|
|
|
|
do_insertion( stage_vector_base &base , const coef_a_type &a , const coef_c_type &c )
|
|
: m_base( base ) , m_a( a ) , m_c( c ) { }
|
|
|
|
template< class Index >
|
|
void operator()( Index ) const
|
|
{
|
|
//boost::fusion::at< Index >( m_base ) = stage< double , Index::value+1 , intermediate_stage >( m_c[ Index::value ] , boost::fusion::at< Index >( m_a ) );
|
|
boost::fusion::at< Index >( m_base ).c = m_c[ Index::value ];
|
|
boost::fusion::at< Index >( m_base ).a = boost::fusion::at< Index >( m_a );
|
|
}
|
|
};
|
|
|
|
struct print_butcher
|
|
{
|
|
const stage_vector_base &m_base;
|
|
std::ostream &m_os;
|
|
|
|
print_butcher( const stage_vector_base &base , std::ostream &os )
|
|
: m_base( base ) , m_os( os )
|
|
{ }
|
|
|
|
template<class Index>
|
|
void operator()(Index) const {
|
|
m_os << boost::fusion::at<Index>(m_base).c << " | ";
|
|
for( size_t i=0 ; i<Index::value ; ++i )
|
|
m_os << boost::fusion::at<Index>(m_base).a[i] << " ";
|
|
m_os << std::endl;
|
|
}
|
|
};
|
|
|
|
|
|
stage_vector( const coef_a_type &a , const coef_b_type &b , const coef_c_type &c )
|
|
{
|
|
typedef boost::mpl::range_c< size_t , 0 , StageCount-1 > indices;
|
|
boost::mpl::for_each< indices >( do_insertion( *this , a , c ) );
|
|
boost::fusion::at_c< StageCount - 1 >( *this ).c = c[ StageCount - 1 ];
|
|
boost::fusion::at_c< StageCount - 1 >( *this ).a = b;
|
|
}
|
|
|
|
void print( std::ostream &os ) const
|
|
{
|
|
typedef boost::mpl::range_c< size_t , 0 , StageCount > indices;
|
|
boost::mpl::for_each< indices >( print_butcher( *this , os ) );
|
|
}
|
|
};
|
|
|
|
|
|
|
|
template< class System , class StateIn , class StateTemp , class DerivIn , class Deriv ,
|
|
class StateOut , class Time >
|
|
struct calculate_stage
|
|
{
|
|
Algebra &algebra;
|
|
System &system;
|
|
const StateIn &x;
|
|
StateTemp &x_tmp;
|
|
StateOut &x_out;
|
|
const DerivIn &dxdt;
|
|
Deriv *F;
|
|
Time t;
|
|
Time dt;
|
|
|
|
calculate_stage( Algebra &_algebra , System &_system , const StateIn &_x , const DerivIn &_dxdt , StateOut &_out ,
|
|
StateTemp &_x_tmp , Deriv *_F , Time _t , Time _dt )
|
|
: algebra( _algebra ) , system( _system ) , x( _x ) , x_tmp( _x_tmp ) , x_out( _out) , dxdt( _dxdt ) , F( _F ) , t( _t ) , dt( _dt )
|
|
{}
|
|
|
|
|
|
template< typename T , size_t stage_number >
|
|
void inline operator()( stage< T , stage_number > const &stage ) const
|
|
//typename stage_fusion_wrapper< T , mpl::size_t< stage_number > , intermediate_stage >::type const &stage ) const
|
|
{
|
|
if( stage_number > 1 )
|
|
{
|
|
#ifdef BOOST_MSVC
|
|
#pragma warning( disable : 4307 34 )
|
|
#endif
|
|
system( x_tmp , F[stage_number-2].m_v , t + stage.c * dt );
|
|
#ifdef BOOST_MSVC
|
|
#pragma warning( default : 4307 34 )
|
|
#endif
|
|
}
|
|
//std::cout << stage_number-2 << ", t': " << t + stage.c * dt << std::endl;
|
|
|
|
if( stage_number < StageCount )
|
|
detail::template generic_rk_call_algebra< stage_number , Algebra >()( algebra , x_tmp , x , dxdt , F ,
|
|
detail::generic_rk_scale_sum< stage_number , Operations , Value , Time >( stage.a , dt) );
|
|
// algebra_type::template for_eachn<stage_number>( x_tmp , x , dxdt , F ,
|
|
// typename operations_type::template scale_sumn< stage_number , time_type >( stage.a , dt ) );
|
|
else
|
|
detail::template generic_rk_call_algebra< stage_number , Algebra >()( algebra , x_out , x , dxdt , F ,
|
|
detail::generic_rk_scale_sum< stage_number , Operations , Value , Time >( stage.a , dt ) );
|
|
// algebra_type::template for_eachn<stage_number>( x_out , x , dxdt , F ,
|
|
// typename operations_type::template scale_sumn< stage_number , time_type >( stage.a , dt ) );
|
|
}
|
|
|
|
};
|
|
|
|
generic_rk_algorithm( const coef_a_type &a , const coef_b_type &b , const coef_c_type &c )
|
|
: m_stages( a , b , c )
|
|
{ }
|
|
|
|
template< class System , class StateIn , class DerivIn , class Time , class StateOut , class StateTemp , class Deriv >
|
|
void inline do_step( Algebra &algebra , System system , const StateIn &in , const DerivIn &dxdt ,
|
|
Time t , StateOut &out , Time dt ,
|
|
StateTemp &x_tmp , Deriv F[StageCount-1] ) const
|
|
{
|
|
typedef typename odeint::unwrap_reference< System >::type unwrapped_system_type;
|
|
unwrapped_system_type &sys = system;
|
|
boost::fusion::for_each( m_stages , calculate_stage<
|
|
unwrapped_system_type , StateIn , StateTemp , DerivIn , Deriv , StateOut , Time >
|
|
( algebra , sys , in , dxdt , out , x_tmp , F , t , dt ) );
|
|
}
|
|
|
|
private:
|
|
stage_vector m_stages;
|
|
};
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // BOOST_NUMERIC_ODEINT_STEPPER_DETAIL_GENERIC_RK_ALGORITHM_HPP_INCLUDED
|