summaryrefslogtreecommitdiff
path: root/libs/numeric/odeint/performance/fusion_explicit_rk_new.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/numeric/odeint/performance/fusion_explicit_rk_new.hpp')
-rw-r--r--libs/numeric/odeint/performance/fusion_explicit_rk_new.hpp217
1 files changed, 217 insertions, 0 deletions
diff --git a/libs/numeric/odeint/performance/fusion_explicit_rk_new.hpp b/libs/numeric/odeint/performance/fusion_explicit_rk_new.hpp
new file mode 100644
index 0000000000..d16a67b5eb
--- /dev/null
+++ b/libs/numeric/odeint/performance/fusion_explicit_rk_new.hpp
@@ -0,0 +1,217 @@
+/*
+ * fusion_runge_kutta.hpp
+ *
+ * Copyright 2010-2011 Mario Mulansky
+ * Copyright 2010-2012 Karsten Ahnert
+ *
+ * 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 FUSION_EXPLICIT_RK_HPP_
+#define FUSION_EXPLICIT_RK_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/container.hpp>
+#include <boost/fusion/algorithm/iteration.hpp>
+
+#include <boost/array.hpp>
+
+#include "fusion_algebra.hpp"
+//#include "fusion_foreach_performance.hpp"
+
+namespace mpl = boost::mpl;
+namespace fusion = boost::fusion;
+
+using namespace std;
+
+struct intermediate_stage {};
+struct last_stage {};
+
+
+
+template< class T , class Constant >
+struct array_wrapper
+{
+ typedef const typename boost::array< T , Constant::value > type;
+};
+
+template< class T , size_t i , class StageCategory >
+struct stage
+{
+ T c;
+ boost::array< T , i > a;
+ typedef StageCategory category;
+};
+
+template< class T , size_t i>
+struct stage< T , i , last_stage >
+{
+ T c;
+ boost::array< T , i > b;
+ typedef last_stage category;
+};
+
+
+
+template< class T , class Constant , class StageCategory >
+struct stage_wrapper
+{
+ typedef stage< T , Constant::value , StageCategory > type;
+};
+
+
+template< class StateType , size_t stage_count >
+class explicit_rk
+{
+
+public:
+
+ typedef StateType state_type;
+
+ typedef mpl::range_c< size_t , 1 , stage_count > stage_indices;
+
+ typedef typename fusion::result_of::as_vector
+ <
+ typename mpl::copy
+ <
+ stage_indices ,
+ mpl::inserter
+ <
+ mpl::vector0< > ,
+ mpl::push_back< mpl::_1 , array_wrapper< double , mpl::_2 > >
+ >
+ >::type
+ >::type coef_a_type;
+
+ typedef boost::array< double , stage_count > coef_b_type;
+ typedef boost::array< double , stage_count > coef_c_type;
+
+ typedef typename fusion::result_of::as_vector
+ <
+ typename mpl::push_back
+ <
+ typename mpl::copy
+ <
+ stage_indices,
+ mpl::inserter
+ <
+ mpl::vector0<> ,
+ mpl::push_back< mpl::_1 , stage_wrapper< double , mpl::_2 , intermediate_stage > >
+ >
+ >::type ,
+ stage< double , stage_count , last_stage >
+ >::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
+ {
+ //fusion::at< Index >( m_base ) = stage< double , Index::value+1 , intermediate_stage >( m_c[ Index::value ] , fusion::at< Index >( m_a ) );
+ fusion::at< Index >( m_base ).c = m_c[ Index::value ];
+ fusion::at< Index >( m_base ).a = fusion::at< Index >( m_a );
+ }
+ };
+
+ stage_vector( const coef_a_type &a , const coef_b_type &b , const coef_c_type &c )
+ {
+ typedef mpl::range_c< size_t , 0 , stage_count - 1 > indices;
+ mpl::for_each< indices >( do_insertion( *this , a , c ) );
+ //fusion::at_c< 0 >( fusion::at_c< stage_count - 1 >( *this ) ) = stage_count - 1 ;
+ fusion::at_c< stage_count - 1 >( *this ).c = c[ stage_count - 1 ];
+ fusion::at_c< stage_count - 1 >( *this ).b = b;
+ }
+ };
+
+
+
+ template< class System >
+ struct calculate_stage
+ {
+ System &system;
+ state_type &x , &x_tmp;
+ state_type *F;
+ const double t;
+ const double dt;
+
+ calculate_stage( System &_system , state_type &_x , state_type &_x_tmp , state_type *_F ,
+ const double _t , const double _dt )
+ : system( _system ) , x( _x ) , x_tmp( _x_tmp ) , F( _F ) , t( _t ) , dt( _dt )
+ {}
+
+
+ template< typename T , size_t stage_number >
+ void inline operator()( stage< T , stage_number , intermediate_stage > const &stage ) const
+ //typename stage_fusion_wrapper< T , mpl::size_t< stage_number > , intermediate_stage >::type const &stage ) const
+ {
+ if( stage_number == 1 )
+ system( x , F[stage_number-1] , t + stage.c * dt );
+ else
+ system( x_tmp , F[stage_number-1] , t + stage.c * dt );
+
+ fusion_algebra<stage_number>::foreach( x_tmp , x , stage.a , F , dt);
+ }
+
+
+ template< typename T , size_t stage_number >
+ void inline operator()( stage< T , stage_number , last_stage > const &stage ) const
+ //void operator()( typename stage_fusion_wrapper< T , mpl::size_t< stage_number > , last_stage >::type const &stage ) const
+ {
+ if( stage_number == 1 )
+ system( x , F[stage_number-1] , t + stage.c * dt );
+ else
+ system( x_tmp , F[stage_number-1] , t + stage.c * dt );
+
+ fusion_algebra<stage_number>::foreach( x , x , stage.b , F , dt);
+ }
+
+
+ };
+
+public:
+
+ explicit_rk( const coef_a_type &a ,
+ const coef_b_type &b ,
+ const coef_c_type &c )
+ : m_stages( a , b , c )
+
+ { }
+
+
+ template< class System >
+ void inline do_step( System system , state_type &x , const double t , const double dt )
+ {
+ fusion::for_each( m_stages , calculate_stage< System >( system , x , m_x_tmp , m_F , t , dt ) );
+ }
+
+private:
+
+ stage_vector m_stages;
+ state_type m_x_tmp;
+
+protected:
+ state_type m_F[stage_count];
+
+};
+
+#endif /* FUSION_EXPLICIT_RK_HPP_ */