phase_oscillator_ensemble.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * phase_oscillator_ensemble.cpp
  3. *
  4. * Demonstrates the phase transition from an unsynchronized to an synchronized state.
  5. *
  6. * Copyright 2011-2012 Karsten Ahnert
  7. * Copyright 2011-2012 Mario Mulansky
  8. * Distributed under the Boost Software License, Version 1.0. (See
  9. * accompanying file LICENSE_1_0.txt or copy at
  10. * http://www.boost.org/LICENSE_1_0.txt)
  11. *
  12. */
  13. #include <iostream>
  14. #include <utility>
  15. #include <boost/numeric/odeint.hpp>
  16. #ifndef M_PI //not there on windows
  17. #define M_PI 3.141592653589793 //...
  18. #endif
  19. #include <boost/random.hpp>
  20. using namespace std;
  21. using namespace boost::numeric::odeint;
  22. //[ phase_oscillator_ensemble_system_function
  23. typedef vector< double > container_type;
  24. pair< double , double > calc_mean_field( const container_type &x )
  25. {
  26. size_t n = x.size();
  27. double cos_sum = 0.0 , sin_sum = 0.0;
  28. for( size_t i=0 ; i<n ; ++i )
  29. {
  30. cos_sum += cos( x[i] );
  31. sin_sum += sin( x[i] );
  32. }
  33. cos_sum /= double( n );
  34. sin_sum /= double( n );
  35. double K = sqrt( cos_sum * cos_sum + sin_sum * sin_sum );
  36. double Theta = atan2( sin_sum , cos_sum );
  37. return make_pair( K , Theta );
  38. }
  39. struct phase_ensemble
  40. {
  41. container_type m_omega;
  42. double m_epsilon;
  43. phase_ensemble( const size_t n , double g = 1.0 , double epsilon = 1.0 )
  44. : m_omega( n , 0.0 ) , m_epsilon( epsilon )
  45. {
  46. create_frequencies( g );
  47. }
  48. void create_frequencies( double g )
  49. {
  50. boost::mt19937 rng;
  51. boost::cauchy_distribution<> cauchy( 0.0 , g );
  52. boost::variate_generator< boost::mt19937&, boost::cauchy_distribution<> > gen( rng , cauchy );
  53. generate( m_omega.begin() , m_omega.end() , gen );
  54. }
  55. void set_epsilon( double epsilon ) { m_epsilon = epsilon; }
  56. double get_epsilon( void ) const { return m_epsilon; }
  57. void operator()( const container_type &x , container_type &dxdt , double /* t */ ) const
  58. {
  59. pair< double , double > mean = calc_mean_field( x );
  60. for( size_t i=0 ; i<x.size() ; ++i )
  61. dxdt[i] = m_omega[i] + m_epsilon * mean.first * sin( mean.second - x[i] );
  62. }
  63. };
  64. //]
  65. //[ phase_oscillator_ensemble_observer
  66. struct statistics_observer
  67. {
  68. double m_K_mean;
  69. size_t m_count;
  70. statistics_observer( void )
  71. : m_K_mean( 0.0 ) , m_count( 0 ) { }
  72. template< class State >
  73. void operator()( const State &x , double t )
  74. {
  75. pair< double , double > mean = calc_mean_field( x );
  76. m_K_mean += mean.first;
  77. ++m_count;
  78. }
  79. double get_K_mean( void ) const { return ( m_count != 0 ) ? m_K_mean / double( m_count ) : 0.0 ; }
  80. void reset( void ) { m_K_mean = 0.0; m_count = 0; }
  81. };
  82. //]
  83. int main( int argc , char **argv )
  84. {
  85. //[ phase_oscillator_ensemble_integration
  86. const size_t n = 16384;
  87. const double dt = 0.1;
  88. container_type x( n );
  89. boost::mt19937 rng;
  90. boost::uniform_real<> unif( 0.0 , 2.0 * M_PI );
  91. boost::variate_generator< boost::mt19937&, boost::uniform_real<> > gen( rng , unif );
  92. // gamma = 1, the phase transition occurs at epsilon = 2
  93. phase_ensemble ensemble( n , 1.0 );
  94. statistics_observer obs;
  95. for( double epsilon = 0.0 ; epsilon < 5.0 ; epsilon += 0.1 )
  96. {
  97. ensemble.set_epsilon( epsilon );
  98. obs.reset();
  99. // start with random initial conditions
  100. generate( x.begin() , x.end() , gen );
  101. // calculate some transients steps
  102. integrate_const( runge_kutta4< container_type >() , boost::ref( ensemble ) , x , 0.0 , 10.0 , dt );
  103. // integrate and compute the statistics
  104. integrate_const( runge_kutta4< container_type >() , boost::ref( ensemble ) , x , 0.0 , 100.0 , dt , boost::ref( obs ) );
  105. cout << epsilon << "\t" << obs.get_K_mean() << endl;
  106. }
  107. //]
  108. return 0;
  109. }