전산물리학:울프_군집_셈법_wolff_cluster_algorithm

This is an old revision of the document!


울프 군집 셈법(Wolff cluster algorithm) 혹은 울프 셈법(Wolff algorithm)은 이징 모형(Ising model)에서 온도 $T$가 $T\neq0$일 때, T에 따라 스핀을 뒤집는 셈법으로 군집 셈법(cluster algorithm) 중 하나이다.

온도 $T$가 주어져 있고 외부 자기장이 없는 경우에 상호작용 세기를 $J=1$, 볼츠만 상수 $k_B = 1$로 가정하면 울프 군집 셈법은 다음과 같은 순서로 작동한다. 일반적인 경우 뒤집히는 확률은 $1-exp(-2\beta J)$다.

  1. 먼저 입자 하나를 무작위로 고른다.
  2. 그 입자의 최근접 이웃 입자 중 같은 스핀을 가진 입자들을 모두 찾고, 찾아진 이웃들에 대해서 더이상 같은 스핀을 가진 최근접 이웃이 없을 때까지 계속하여 찾는다.
  3. 1번에서 선택된 입자의 스핀을 뒤집고, 2번에서 찾은 입자들의 스핀을 $1-exp(-2/T)$의 확률로 뒤집는다.
  4. 1번으로 돌아가서 2~3번을 반복한다.

결과적으로 아래와 같은 그림처럼 한 스텝에 입자들이 군집을 이뤄서 뒤집히게 된다.

<color #ffffff>……………………………</color>

다음은 울프 셈법으로 주기적 경계(periodic boundary)를 갖는 128$\times$128 크기의 정사각 격자(square latice)에서 단계(step)별 자화(magnetization)를 구하고 파일로 내보내는 C++코드이다. 초기 상태는 모두가 한 방향으로 정렬되어 있는 상태다.

<Code:C++ | wolff.cpp> #include <fstream> #include <cmath> #include <vector> #include <deque> #include <random>

using std::vector; using std::deque; using std::ofstream; using std::random_device; using std::uniform_real_distribution; using std::uniform_int_distribution; using std::mt19937_64; using std::exp; using std::abs; using std::pow;

random_device rd; mt19937_64 rng(rd()); uniform_real_distribution<double> dds(0,1);

void Wolff(int N, int k, vector<int> &S, vector<vector<int» A, double p, double &m);

int main() {

  int N = 128;//lattice length
  double T = 4.0;//given temparature
  
  double p = 1.0-exp(-2.0/T);//flip probability
  double m = 1.0; //magnetization
  int mcs_max = (int)(pow(2,20)+0.5); //max montecarlo step
  int eq_time = 100000; //equilibrium time
 
  vector<int> S(N*N, 1);//spin information array
  vector<vector<int>> A(N*N, vector<int>(4,-1));//the closest neighbor information
  for(int i = 0; i < N; ++i)
  {
      for(int j = 0; j < N; ++j)
      {
          A[i*N + j][0] = i*N + (j+1)%N; //the right particle
          A[i*N + j][1] = i*N + (j-1+N)%N; //the left particle
          A[i*N + j][2] = ((i+1)%N)*N + j; //the above particle
          A[i*N + j][3] = ((i-1+N)%N)*N + j; //the below particle
      }
  }
  ofstream fout;
  fout.open("mag.dat"); //output file
  //equlibrium step
  for(int i = 0; i < eq_time; ++i)
  {
      int loc = ids(rng);
      Wolff(N, loc, S, A, p, m);
  }
  uniform_int_distribution<int> ids(0,(N*N)-1);
  
  //measure the magnetization
  for(int i = 0; i < mcs_max; ++i)
  {
      int loc = ids(rng);
      Wolff(N, loc, S, A, p, m);
      fout << i << "," << m << "\n";
  }
  fout.close();

}

void Wolff(int N, int k, vector<int> &S, vector<vector<int» A, double p, double &m) {

  int nc = 1; //# of cluster
  int s0 = S[k]; //the spin information of selected particle
  int ind = -1; //the particle index
  S[k] = -s0; // flip spin
  deque<int> dq; //queue for saving same spin neighbor index
  dq.emplace_back(k); //save selected particle's index
  dq.shrink_to_fit(); //free memories which are not used
  
  while(!dq.empty())
  {
      ind = dq.front(); //extract information of the leftmost queue
      dq.pop_front(); //remove the leftmost queue
      for(int j = 0; j < A[ind].capacity(); ++j)
      {
          if(S[A[ind][j]] == s0) //compare the spins
          {
              if(dds(rng) < p) //proceed in the probability p
              {
                  dq.emplace_back(A[ind][j]);//save the neigbor's index
                  dq.shrink_to_fit();//free memories
                  S[A[ind][j]] = -s0;//flip spin
                  ++nc; //add 1 to # of cluster
              }
          }
      }
  }
  m = 0.0;
  //calculating the magnetization
  for(int i = 0; i < S.capacity(); ++i)
  {
      m += (double)S[i]/(N*N);
  }
  m = abs(m);

} </Code>

함께 보기

  • 전산물리학/울프_군집_셈법_wolff_cluster_algorithm.1642403398.txt.gz
  • Last modified: 2023/09/05 15:46
  • (external edit)