lattice2d.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. Copyright 2011 Mario Mulansky
  3. Copyright 2012-2013 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. /* strongly nonlinear hamiltonian lattice in 2d */
  9. #ifndef LATTICE2D_HPP
  10. #define LATTICE2D_HPP
  11. #include <vector>
  12. #include <boost/math/special_functions/pow.hpp>
  13. using boost::math::pow;
  14. template< int Kappa , int Lambda >
  15. struct lattice2d {
  16. const double m_beta;
  17. std::vector< std::vector< double > > m_omega;
  18. lattice2d( const double beta )
  19. : m_beta( beta )
  20. { }
  21. template< class StateIn , class StateOut >
  22. void operator()( const StateIn &q , StateOut &dpdt )
  23. {
  24. // q and dpdt are 2d
  25. const int N = q.size();
  26. int i;
  27. for( i = 0 ; i < N ; ++i )
  28. {
  29. const int i_l = (i-1+N) % N;
  30. const int i_r = (i+1) % N;
  31. for( int j = 0 ; j < N ; ++j )
  32. {
  33. const int j_l = (j-1+N) % N;
  34. const int j_r = (j+1) % N;
  35. dpdt[i][j] = - m_omega[i][j] * pow<Kappa-1>( q[i][j] )
  36. - m_beta * pow<Lambda-1>( q[i][j] - q[i][j_l] )
  37. - m_beta * pow<Lambda-1>( q[i][j] - q[i][j_r] )
  38. - m_beta * pow<Lambda-1>( q[i][j] - q[i_l][j] )
  39. - m_beta * pow<Lambda-1>( q[i][j] - q[i_r][j] );
  40. }
  41. }
  42. }
  43. template< class StateIn >
  44. double energy( const StateIn &q , const StateIn &p )
  45. {
  46. // q and dpdt are 2d
  47. const int N = q.size();
  48. double energy = 0.0;
  49. int i;
  50. for( i = 0 ; i < N ; ++i )
  51. {
  52. const int i_l = (i-1+N) % N;
  53. const int i_r = (i+1) % N;
  54. for( int j = 0 ; j < N ; ++j )
  55. {
  56. const int j_l = (j-1+N) % N;
  57. const int j_r = (j+1) % N;
  58. energy += p[i][j]*p[i][j] / 2.0
  59. + m_omega[i][j] * pow<Kappa>( q[i][j] ) / Kappa
  60. + m_beta * pow<Lambda>( q[i][j] - q[i][j_l] ) / Lambda / 2
  61. + m_beta * pow<Lambda>( q[i][j] - q[i][j_r] ) / Lambda / 2
  62. + m_beta * pow<Lambda>( q[i][j] - q[i_l][j] ) / Lambda / 2
  63. + m_beta * pow<Lambda>( q[i][j] - q[i_r][j] ) / Lambda / 2;
  64. }
  65. }
  66. return energy;
  67. }
  68. template< class StateIn , class StateOut >
  69. double local_energy( const StateIn &q , const StateIn &p , StateOut &energy )
  70. {
  71. // q and dpdt are 2d
  72. const int N = q.size();
  73. double e = 0.0;
  74. int i;
  75. for( i = 0 ; i < N ; ++i )
  76. {
  77. const int i_l = (i-1+N) % N;
  78. const int i_r = (i+1) % N;
  79. for( int j = 0 ; j < N ; ++j )
  80. {
  81. const int j_l = (j-1+N) % N;
  82. const int j_r = (j+1) % N;
  83. energy[i][j] = p[i][j]*p[i][j] / 2.0
  84. + m_omega[i][j] * pow<Kappa>( q[i][j] ) / Kappa
  85. + m_beta * pow<Lambda>( q[i][j] - q[i][j_l] ) / Lambda / 2
  86. + m_beta * pow<Lambda>( q[i][j] - q[i][j_r] ) / Lambda / 2
  87. + m_beta * pow<Lambda>( q[i][j] - q[i_l][j] ) / Lambda / 2
  88. + m_beta * pow<Lambda>( q[i][j] - q[i_r][j] ) / Lambda / 2;
  89. e += energy[i][j];
  90. }
  91. }
  92. //rescale
  93. e = 1.0/e;
  94. for( i = 0 ; i < N ; ++i )
  95. for( int j = 0 ; j < N ; ++j )
  96. energy[i][j] *= e;
  97. return 1.0/e;
  98. }
  99. void load_pot( const char* filename , const double W , const double gap ,
  100. const size_t dim )
  101. {
  102. std::ifstream in( filename , std::ios::in | std::ios::binary );
  103. if( !in.is_open() ) {
  104. std::cerr << "pot file not found: " << filename << std::endl;
  105. exit(0);
  106. } else {
  107. std::cout << "using pot file: " << filename << std::endl;
  108. }
  109. m_omega.resize( dim );
  110. for( int i = 0 ; i < dim ; ++i )
  111. {
  112. m_omega[i].resize( dim );
  113. for( size_t j = 0 ; j < dim ; ++j )
  114. {
  115. if( !in.good() )
  116. {
  117. std::cerr << "I/O Error: " << filename << std::endl;
  118. exit(0);
  119. }
  120. double d;
  121. in.read( (char*) &d , sizeof(d) );
  122. if( (d < 0) || (d > 1.0) )
  123. {
  124. std::cerr << "ERROR: " << d << std::endl;
  125. exit(0);
  126. }
  127. m_omega[i][j] = W*d + gap;
  128. }
  129. }
  130. }
  131. void generate_pot( const double W , const double gap , const size_t dim )
  132. {
  133. m_omega.resize( dim );
  134. for( size_t i = 0 ; i < dim ; ++i )
  135. {
  136. m_omega[i].resize( dim );
  137. for( size_t j = 0 ; j < dim ; ++j )
  138. {
  139. m_omega[i][j] = W*static_cast<double>(rand())/RAND_MAX + gap;
  140. }
  141. }
  142. }
  143. };
  144. #endif