heun.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. [auto_generated]
  3. libs/numeric/odeint/examples/heun.cpp
  4. [begin_description]
  5. Examplary implementation of the method of Heun.
  6. [end_description]
  7. Copyright 2012 Karsten Ahnert
  8. Copyright 2012 Mario Mulansky
  9. Distributed under the Boost Software License, Version 1.0.
  10. (See accompanying file LICENSE_1_0.txt or
  11. copy at http://www.boost.org/LICENSE_1_0.txt)
  12. */
  13. #include <iostream>
  14. #include <boost/fusion/container/vector.hpp>
  15. #include <boost/fusion/container/generation/make_vector.hpp>
  16. #include <boost/array.hpp>
  17. #include <boost/numeric/odeint.hpp>
  18. namespace fusion = boost::fusion;
  19. //[ heun_define_coefficients
  20. template< class Value = double >
  21. struct heun_a1 : boost::array< Value , 1 > {
  22. heun_a1( void )
  23. {
  24. (*this)[0] = static_cast< Value >( 1 ) / static_cast< Value >( 3 );
  25. }
  26. };
  27. template< class Value = double >
  28. struct heun_a2 : boost::array< Value , 2 >
  29. {
  30. heun_a2( void )
  31. {
  32. (*this)[0] = static_cast< Value >( 0 );
  33. (*this)[1] = static_cast< Value >( 2 ) / static_cast< Value >( 3 );
  34. }
  35. };
  36. template< class Value = double >
  37. struct heun_b : boost::array< Value , 3 >
  38. {
  39. heun_b( void )
  40. {
  41. (*this)[0] = static_cast<Value>( 1 ) / static_cast<Value>( 4 );
  42. (*this)[1] = static_cast<Value>( 0 );
  43. (*this)[2] = static_cast<Value>( 3 ) / static_cast<Value>( 4 );
  44. }
  45. };
  46. template< class Value = double >
  47. struct heun_c : boost::array< Value , 3 >
  48. {
  49. heun_c( void )
  50. {
  51. (*this)[0] = static_cast< Value >( 0 );
  52. (*this)[1] = static_cast< Value >( 1 ) / static_cast< Value >( 3 );
  53. (*this)[2] = static_cast< Value >( 2 ) / static_cast< Value >( 3 );
  54. }
  55. };
  56. //]
  57. //[ heun_stepper_definition
  58. template<
  59. class State ,
  60. class Value = double ,
  61. class Deriv = State ,
  62. class Time = Value ,
  63. class Algebra = boost::numeric::odeint::range_algebra ,
  64. class Operations = boost::numeric::odeint::default_operations ,
  65. class Resizer = boost::numeric::odeint::initially_resizer
  66. >
  67. class heun : public
  68. boost::numeric::odeint::explicit_generic_rk< 3 , 3 , State , Value , Deriv , Time ,
  69. Algebra , Operations , Resizer >
  70. {
  71. public:
  72. typedef boost::numeric::odeint::explicit_generic_rk< 3 , 3 , State , Value , Deriv , Time ,
  73. Algebra , Operations , Resizer > stepper_base_type;
  74. typedef typename stepper_base_type::state_type state_type;
  75. typedef typename stepper_base_type::wrapped_state_type wrapped_state_type;
  76. typedef typename stepper_base_type::value_type value_type;
  77. typedef typename stepper_base_type::deriv_type deriv_type;
  78. typedef typename stepper_base_type::wrapped_deriv_type wrapped_deriv_type;
  79. typedef typename stepper_base_type::time_type time_type;
  80. typedef typename stepper_base_type::algebra_type algebra_type;
  81. typedef typename stepper_base_type::operations_type operations_type;
  82. typedef typename stepper_base_type::resizer_type resizer_type;
  83. typedef typename stepper_base_type::stepper_type stepper_type;
  84. heun( const algebra_type &algebra = algebra_type() )
  85. : stepper_base_type(
  86. fusion::make_vector(
  87. heun_a1<Value>() ,
  88. heun_a2<Value>() ) ,
  89. heun_b<Value>() , heun_c<Value>() , algebra )
  90. { }
  91. };
  92. //]
  93. const double sigma = 10.0;
  94. const double R = 28.0;
  95. const double b = 8.0 / 3.0;
  96. struct lorenz
  97. {
  98. template< class State , class Deriv >
  99. void operator()( const State &x_ , Deriv &dxdt_ , double t ) const
  100. {
  101. typename boost::range_iterator< const State >::type x = boost::begin( x_ );
  102. typename boost::range_iterator< Deriv >::type dxdt = boost::begin( dxdt_ );
  103. dxdt[0] = sigma * ( x[1] - x[0] );
  104. dxdt[1] = R * x[0] - x[1] - x[0] * x[2];
  105. dxdt[2] = -b * x[2] + x[0] * x[1];
  106. }
  107. };
  108. struct streaming_observer
  109. {
  110. std::ostream &m_out;
  111. streaming_observer( std::ostream &out ) : m_out( out ) { }
  112. template< typename State , typename Value >
  113. void operator()( const State &x , Value t ) const
  114. {
  115. m_out << t;
  116. for( size_t i=0 ; i<x.size() ; ++i ) m_out << "\t" << x[i];
  117. m_out << "\n";
  118. }
  119. };
  120. int main( int argc , char **argv )
  121. {
  122. using namespace std;
  123. using namespace boost::numeric::odeint;
  124. //[ heun_example
  125. typedef boost::array< double , 3 > state_type;
  126. heun< state_type > h;
  127. state_type x = {{ 10.0 , 10.0 , 10.0 }};
  128. integrate_const( h , lorenz() , x , 0.0 , 100.0 , 0.01 ,
  129. streaming_observer( std::cout ) );
  130. //]
  131. return 0;
  132. }