在Python中使用Ising模型

时间:2016-04-12 22:52:37

标签: python python-3.x physics montecarlo

我目前正致力于使用Python3为Ising Model编写代码。我对编码还很陌生。我有工作代码,但输出结果不符合预期,我似乎无法找到错误。这是我的代码:

import numpy as np
import random


def init_spin_array(rows, cols):
    return np.random.choice((-1, 1), size=(rows, cols))


def find_neighbors(spin_array, lattice, x, y):
    left = (x , y - 1)
    right = (x, y + 1 if y + 1 < (lattice - 1) else 0)
    top = (x - 1, y)
    bottom = (x + 1 if x + 1 < (lattice - 1) else 0, y)

    return [spin_array[left[0], left[1]],
            spin_array[right[0], right[1]],
            spin_array[top[0], top[1]],
            spin_array[bottom[0], bottom[1]]]

def energy(spin_array, lattice, x ,y):
    return -1 * spin_array[x, y] * sum(find_neighbors(spin_array, lattice, x, y))


def main():
    lattice = eval(input("Enter lattice size: "))
    temperature = eval(input("Enter the temperature: "))
    sweeps = eval(input("Enter the number of Monte Carlo Sweeps: "))
    spin_array = init_spin_array(lattice, lattice)
    print("Original System: \n", spin_array)
    # the Monte Carlo follows below
    for sweep in range(sweeps):
        for i in range(lattice):
            for j in range(lattice):
                e = energy(spin_array, lattice, i, j)
                if e <= 0:
                spin_array[i, j] *= -1
            elif np.exp(-1 * e/temperature) > random.randint(0, 1):
                spin_array[i, j] *= -1
            else:
                continue
print("Modified System: \n", spin_array)

main()

我认为错误发生在蒙特卡洛循环中,但我不确定。该系统应在低温下高度有序,并在临界温度2.27以后变得无序。换句话说,随着T接近2.27,系统的随机性应该增加。例如,在T = .1时,我们应该看到对齐的大块自旋,即-1和1的补丁。过去2.27系统应该是无序的,我们不应该看到这些补丁。

1 个答案:

答案 0 :(得分:4)

如果您要包括系统大小,扫描次数和平均manetisation,那么您的问题会更有意义。订购了多少个中间配置,有多少个无序? MC是一种采样技术 - 单个配置没有任何意义,低温下可能(并且将会)是无序状态,高T处有序状态。装配属性(平均磁化强度)是有意义的。

无论如何,你的代码中有三个错误:一个小错误,一个中等错误,一个非常严重的错误。

小问题是您在find_neighbors中搜索邻居时忽略整行和整列:

right = (x, y + 1 if y + 1 < (lattice - 1) else 0)

应该是:

right = (x, y + 1 if y + 1 < lattice else 0)

甚至更好:

right = (x, (y + 1) % lattice)

同样适用于bottom

中等的一个是你对能量差的计算偏差了两倍:

def energy(spin_array, lattice, x ,y):
   return -1 * spin_array[x, y] * sum(find_neighbors(spin_array, lattice, x, y))
          ^^

因子实际上是2*J,其中J是耦合常数,因此-1表示:

  1. 你的临界温度减半,更重要的是......
  2. 你有反铁磁自旋相互作用(J <0),因此即使在非常低的温度下也没有任何有序状态。
  3. 然而,最糟糕的错误是使用random.randint()进行拒绝抽样:

    elif np.exp(-1 * e/temperature) > random.randint(0, 1):
        spin_array[i, j] *= -1
    

    您应该使用random.random()代替,否则转换概率将始终为50%。

    以下是对程序的修改,可自动扫描温度范围从0.1到5.0:

    import numpy as np
    import random
    
    
    def init_spin_array(rows, cols):
        return np.ones((rows, cols))
    
    
    def find_neighbors(spin_array, lattice, x, y):
        left   = (x, y - 1)
        right  = (x, (y + 1) % lattice)
        top    = (x - 1, y)
        bottom = ((x + 1) % lattice, y)
    
        return [spin_array[left[0], left[1]],
                spin_array[right[0], right[1]],
                spin_array[top[0], top[1]],
                spin_array[bottom[0], bottom[1]]]
    
    
    def energy(spin_array, lattice, x ,y):
        return 2 * spin_array[x, y] * sum(find_neighbors(spin_array, lattice, x, y))
    
    
    def main():
        RELAX_SWEEPS = 50
        lattice = eval(input("Enter lattice size: "))
        sweeps = eval(input("Enter the number of Monte Carlo Sweeps: "))
        for temperature in np.arange(0.1, 5.0, 0.1):
            spin_array = init_spin_array(lattice, lattice)
            # the Monte Carlo follows below
            mag = np.zeros(sweeps + RELAX_SWEEPS)
            for sweep in range(sweeps + RELAX_SWEEPS):
                for i in range(lattice):
                    for j in range(lattice):
                        e = energy(spin_array, lattice, i, j)
                        if e <= 0:
                            spin_array[i, j] *= -1
                        elif np.exp((-1.0 * e)/temperature) > random.random():
                            spin_array[i, j] *= -1
                mag[sweep] = abs(sum(sum(spin_array))) / (lattice ** 2)
            print(temperature, sum(mag[RELAX_SWEEPS:]) / sweeps)
    
    
    main()
    

    20x20和100x100格子以及100次扫描的结果:

    Average mangentisation as a function of the reduced temperature

    起始配置是完全有序的配置,以防止在低温下非常稳定的畴壁的发展。此外,最初还进行了30次额外扫描,以便对系统进行热处理(接近临界温度时不够,但Metropolis-Hastings算法无法正确处理那里的严重减速)。