phase_oscillator_chain.cu 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. Copyright 2011-2013 Mario Mulansky
  3. Copyright 2011 Karsten Ahnert
  4. Distributed under the Boost Software License, Version 1.0.
  5. (See accompanying file LICENSE_1_0.txt or
  6. copy at http://www.boost.org/LICENSE_1_0.txt)
  7. */
  8. /*
  9. * This example shows how to use odeint on CUDA devices with thrust.
  10. * Note that we require at least Version 3.2 of the nVidia CUDA SDK
  11. * and the thrust library should be installed in the CUDA include
  12. * folder.
  13. *
  14. * As example we use a chain of phase oscillators with nearest neighbour
  15. * coupling, as described in:
  16. *
  17. * Avis H. Cohen, Philip J. Holmes and Richard H. Rand:
  18. * JOURNAL OF MATHEMATICAL BIOLOGY Volume 13, Number 3, 345-369,
  19. *
  20. */
  21. #include <iostream>
  22. #include <cmath>
  23. #include <thrust/device_vector.h>
  24. #include <thrust/iterator/permutation_iterator.h>
  25. #include <thrust/iterator/counting_iterator.h>
  26. #include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
  27. #include <boost/numeric/odeint/integrate/integrate_const.hpp>
  28. #include <boost/numeric/odeint/external/thrust/thrust.hpp>
  29. using namespace std;
  30. using namespace boost::numeric::odeint;
  31. //change this to float if your device does not support double computation
  32. typedef double value_type;
  33. //[ thrust_phase_chain_system
  34. //change this to host_vector< ... > if you want to run on CPU
  35. typedef thrust::device_vector< value_type > state_type;
  36. typedef thrust::device_vector< size_t > index_vector_type;
  37. //typedef thrust::host_vector< value_type > state_type;
  38. //typedef thrust::host_vector< size_t > index_vector_type;
  39. //<-
  40. /*
  41. * This implements the rhs of the dynamical equation:
  42. * \phi'_0 = \omega_0 + sin( \phi_1 - \phi_0 )
  43. * \phi'_i = \omega_i + sin( \phi_i+1 - \phi_i ) + sin( \phi_i - \phi_i-1 )
  44. * \phi'_N-1 = \omega_N-1 + sin( \phi_N-1 - \phi_N-2 )
  45. */
  46. //->
  47. class phase_oscillators
  48. {
  49. public:
  50. struct sys_functor
  51. {
  52. template< class Tuple >
  53. __host__ __device__
  54. void operator()( Tuple t ) // this functor works on tuples of values
  55. {
  56. // first, unpack the tuple into value, neighbors and omega
  57. const value_type phi = thrust::get<0>(t);
  58. const value_type phi_left = thrust::get<1>(t); // left neighbor
  59. const value_type phi_right = thrust::get<2>(t); // right neighbor
  60. const value_type omega = thrust::get<3>(t);
  61. // the dynamical equation
  62. thrust::get<4>(t) = omega + sin( phi_right - phi ) + sin( phi - phi_left );
  63. }
  64. };
  65. phase_oscillators( const state_type &omega )
  66. : m_omega( omega ) , m_N( omega.size() ) , m_prev( omega.size() ) , m_next( omega.size() )
  67. {
  68. // build indices pointing to left and right neighbours
  69. thrust::counting_iterator<size_t> c( 0 );
  70. thrust::copy( c , c+m_N-1 , m_prev.begin()+1 );
  71. m_prev[0] = 0; // m_prev = { 0 , 0 , 1 , 2 , 3 , ... , N-1 }
  72. thrust::copy( c+1 , c+m_N , m_next.begin() );
  73. m_next[m_N-1] = m_N-1; // m_next = { 1 , 2 , 3 , ... , N-1 , N-1 }
  74. }
  75. void operator() ( const state_type &x , state_type &dxdt , const value_type dt )
  76. {
  77. thrust::for_each(
  78. thrust::make_zip_iterator(
  79. thrust::make_tuple(
  80. x.begin() ,
  81. thrust::make_permutation_iterator( x.begin() , m_prev.begin() ) ,
  82. thrust::make_permutation_iterator( x.begin() , m_next.begin() ) ,
  83. m_omega.begin() ,
  84. dxdt.begin()
  85. ) ),
  86. thrust::make_zip_iterator(
  87. thrust::make_tuple(
  88. x.end() ,
  89. thrust::make_permutation_iterator( x.begin() , m_prev.end() ) ,
  90. thrust::make_permutation_iterator( x.begin() , m_next.end() ) ,
  91. m_omega.end() ,
  92. dxdt.end()) ) ,
  93. sys_functor()
  94. );
  95. }
  96. private:
  97. const state_type &m_omega;
  98. const size_t m_N;
  99. index_vector_type m_prev;
  100. index_vector_type m_next;
  101. };
  102. //]
  103. const size_t N = 32768;
  104. const value_type pi = 3.1415926535897932384626433832795029;
  105. const value_type epsilon = 6.0 / ( N * N ); // should be < 8/N^2 to see phase locking
  106. const value_type dt = 0.1;
  107. int main( int arc , char* argv[] )
  108. {
  109. //[ thrust_phase_chain_integration
  110. // create initial conditions and omegas on host:
  111. vector< value_type > x_host( N );
  112. vector< value_type > omega_host( N );
  113. for( size_t i=0 ; i<N ; ++i )
  114. {
  115. x_host[i] = 2.0 * pi * drand48();
  116. omega_host[i] = ( N - i ) * epsilon; // decreasing frequencies
  117. }
  118. // copy to device
  119. state_type x = x_host;
  120. state_type omega = omega_host;
  121. // create stepper
  122. runge_kutta4< state_type , value_type , state_type , value_type > stepper;
  123. // create phase oscillator system function
  124. phase_oscillators sys( omega );
  125. // integrate
  126. integrate_const( stepper , sys , x , 0.0 , 10.0 , dt );
  127. thrust::copy( x.begin() , x.end() , std::ostream_iterator< value_type >( std::cout , "\n" ) );
  128. std::cout << std::endl;
  129. //]
  130. }