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

This is an old revision of the document!


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

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

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

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

다음은 울프 셈법으로 주기적 경계(periodic boundary)를 갖는 128×128 크기의 정사각 격자(square latice)에서 단계(step)별 자화(magnetization)를 구하고 파일로 내보내는 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);
}

함께 보기

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