Click here to Skip to main content
15,886,810 members
Articles / Programming Languages / CUDA

odeint v2 - Solving ordinary differential equations in C++

Rate me:
Please Sign up or sign in to vote.
4.64/5 (18 votes)
19 Oct 2011CPOL19 min read 129.2K   2.8K   34  
odeint v2 - Solving ordinary differential equations in C++
/*
 * generic_stepper.hpp
 *
 *  Created on: Nov 12, 2010
 *      Author: mario
 */

#ifndef GENERIC_STEPPER_HPP_
#define GENERIC_STEPPER_HPP_


#include <boost/mpl/vector.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/zip_view.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/insert_range.hpp>

#include <vector>

#include "algebra.hpp"

namespace mpl = boost::mpl;

using namespace std;


/*
 * c_1 |
 * c_2 | a_{2,1}
 * c_3 | a_{3,1} a_{3,2}
 * ...
 * c_s | a_{s,1} a_{s,2} ... a_{s,s-1}
 * -----------------------------------
 *     | b_1     b_2         b_{s-1}    b_s
 */


/* Runge Kutta Stages */


template< typename State , size_t stage >
class stepper_stage
{

public:

    typedef double value_type;
    typedef State state_type;
    typedef vector< vector< double > > parameter_array_type2D;
    typedef vector< double > parameter_array_type1D;


    void init( parameter_array_type2D &a , parameter_array_type1D &c )
    {
        m_a_row = a[stage-1];
        m_c = c[stage-1];
    }

    template< typename System >
    void operator() ( System &system , state_type &x_tmp , const state_type &x , const state_type *k_vector , double t , const double dt )
    {
        system( x_tmp , k_vector[stage-1] , t + m_c * dt );
        algebra<state_type , stage>::foreach< stage >( x_tmp , x , m_a_row , k_vector , dt);
    }

private:

    vector< value_type > m_a_row;
    value_type m_c;

};


template< typename State >
class stepper_stage< State , 1 >
{

public:

    typedef double value_type;
    typedef State state_type;
    typedef vector< vector< double > > parameter_array_type2D;
    typedef vector< double > parameter_array_type1D;


    void init( parameter_array_type2D &a , parameter_array_type1D &c )
    {
    	m_a_row = a[0];
        m_c = c[0];
    }

    template< typename System >
    void operator() ( System &system , state_type &x_tmp , const state_type &x , const state_type *k_vector , double t , const double dt )
    {
        system( x , k_vector[0] , t + m_c * dt );
        algebra<state_type , 1>::foreach( x_tmp , x , m_a_row , k_vector , dt);
    }

private:

    vector< value_type > m_a_row;
    value_type m_c;

};


template< typename State , size_t stage >
class stepper_last_stage
{

public:

    typedef double value_type;
    typedef State state_type;
    typedef vector< vector< double > > parameter_array_type2D;
    typedef vector< double > parameter_array_type1D;


    void init( const parameter_array_type1D &b , const parameter_array_type1D &c )
    {
        m_b = b;
        m_c = c[stage-1];
    }

    template< typename System >
    void operator() ( System &system , state_type &x_tmp , state_type &x , state_type *k_vector , double t , const double dt )
    {
        system( x_tmp , k_vector[stage-1] , t + m_c * dt );
        algebra<state_type , stage>::foreach( x , x , m_b , k_vector , dt);
    }

private:

    vector< value_type > m_b;
    value_type m_c;

};


template< typename State >
class stepper_last_stage< State , 1 >
{

public:

    typedef double value_type;
    typedef State state_type;
    typedef vector< vector< double > > parameter_array_type2D;
    typedef vector< double > parameter_array_type1D;


    void init( const parameter_array_type1D &b , const parameter_array_type1D &c )
    {
        m_b = b;
        m_c = c[0];
    }

    template< typename System >
    void do_step( System &system , state_type &x_tmp , state_type &x , state_type k_vector[1] , double t , const double dt )
    {
        system( x , k_vector[0] , t + m_c * dt );
        algebra<state_type , 1>::foreach( x , x , m_b , k_vector , dt);
    }

private:

    vector< value_type > m_b;
    value_type m_c;

};


/* Runge Kutta Stepper - consisting of several stages */

template< typename State , size_t stage_count >
class runge_kutta_stepper
{

	typedef State state_type;
	typedef vector< vector< double > > parameter_array_type2D;
	typedef vector< double > parameter_array_type1D;

    template< class System >
    struct calculate_stage
    {
    	System &system;
    	state_type &x , &x_tmp;
    	state_type *k_vector;
    	const double t;
    	const double dt;
    	const parameter_array_type2D &m_a;
    	const parameter_array_type1D &m_b;
    	const parameter_array_type1D &m_c;

    	calculate_stage( System &_system , state_type &_x , state_type &_x_tmp , state_type *_k_vector ,
    						const double _t , const double _dt ,
    						const parameter_array_type2D &a ,
    						const parameter_array_type1D &b ,
    						const parameter_array_type1D &c )
    	: system( _system ) , x( _x ) , x_tmp( _x_tmp ) , k_vector( _k_vector ) , t( _t ) , dt( _dt ),
    	  m_a( a ) , m_b( b ) , m_c( c )
    	{}

    	template< class Stage >
    	void operator()( Stage &s )
    	{
    		s.init( m_a , m_b , m_c );
    		s( x_tmp , x , k_vector , t , dt );
    	}

    };

public:

    typedef mpl::range_c< size_t , 1 , stage_count > indices;
    typedef typename mpl::copy // create mpl::vector< stepper_stage< 0 >, stepper_stage< 1 > , .. stepper_stage< stage_count-1 > >
    <
      indices ,
      mpl::inserter
      <
        mpl::vector0<> ,
        stepper_stage< State , mpl::_2::value >
      >
    >::type stage_vector;
    typedef stepper_last_stage< State , stage_count > last_stage_type;

    runge_kutta_stepper( const parameter_array_type2D &a ,
							const parameter_array_type1D &b ,
							const parameter_array_type1D &c )
    	: m_a( a ) , m_b( b ) , m_c( c )
    {
    	last_stage.init( b , c );
    }

    template< class System >
    void do_step( System &system , state_type &x , double t , const double dt )
    {
        mpl::for_each< stage_vector >( calculate_stage< System >( system , x , m_x_tmp , m_k_vector , t , dt ,
        													 	   m_a , m_b , m_c ) );
        last_stage.do_step( system , m_x_tmp , x , m_k_vector , t , dt );
    }

private:

	state_type m_k_vector[stage_count];
	state_type m_x_tmp;
	last_stage_type last_stage;
	const parameter_array_type2D &m_a;
	const parameter_array_type1D &m_b;
	const parameter_array_type1D &m_c;
};


#endif /* GENERIC_STEPPER_HPP_ */

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions