Ising模型都会算法
我正在尝试使用都会算法来模拟伊辛模型。我遇到的问题是代码不会一直稳定。对于高 beta 值,能量偏好应该是自旋都在同一方向,但是在我的代码中,即使它在大部分时间都有效,偶尔会出现水平或垂直的向上旋转带,然后向下旋转网格(网格2)。然后,这使得平均旋转计数稳定在一个不是 1 或 -1 的值,而高 Beta 值应为 1 或 -1。我知道问题出在哪里 - 当这种情况发生时,我在边界处的 delta 能量是 4,因此在高 beta 值下,这使得自旋不太可能翻转,因此最终会被卡住。我在想,也许我运行的时间不够长,但查看变量资源管理器上的average_spin_count,它似乎在最多 200 圈后稳定下来。我也在想也许使用对角线,但其他代码和模拟似乎没有使用这个想法,所以我希望有人能指出我哪里出错了。 (您必须多次运行代码,直到遇到并非所有旋转都向上/向下的情况)。谢谢
import numpy as np
import numpy.random as rnd
N = 20
#grid size
random_number = np.random.randint(0,1000)
prob = 0.5
#probability of starting with spin down.
np.random.seed(random_number)
grid =np.random.choice(list(range(-1, 0)) + list(range(1, 2)), size=(N, N), p=[prob,1-prob])
def find_energy(grid, r, c):
if r < N-1 and c < N-1:
energy = -((grid[r,c]*grid[r+1,c])+(grid[r,c]*grid[r-1,c])+
(grid[r,c]*grid[r,c+1])+(grid[r,c]*grid[r,c-1]))
if r == (N-1) and c < N-1:
energy = -((grid[r,c]*grid[0,c])+(grid[r,c]*grid[r-1,c])+
(grid[r,c]*grid[r,c+1])+(grid[r,c]*grid[r,c-1]))
if c == (N-1) and r < N-1:
energy = -((grid[r,c]*grid[r+1,c])+(grid[r,c]*grid[r-1,c])+
(grid[r,c]*grid[r,0])+(grid[r,c]*grid[r,c-1]))
if c== (N-1) and r==(N-1):
energy = -((grid[r,c]*grid[0,c])+(grid[r,c]*grid[r-1,c])+
(grid[r,c]*grid[r,0])+(grid[r,c]*grid[r,c-1]))
return energy
def get_coordinate():
"""Returns a random coordinate as a tuple"""
return tuple(np.random.randint(0, high=N, size=(1, 2))[0])
def probability( delta_energy, beta):
probability = np.exp(-1*beta*delta_energy)
return probability
def compare_energies(n, beta):
total_number_spin_up=np.array([])
total_number_spin_down=np.array([])
for i in range(n):
original_point = get_coordinate()
original_energy = find_energy(grid, original_point[0], original_point[1])
new_energy = original_energy * -1
delta_energy = new_energy-original_energy
x = (original_point[0])
y = (original_point[1])
if delta_energy <= 0:
grid[x,y] = grid[x, y]*-1
#flips the spin
elif delta_energy > 0:
if probability(delta_energy, beta) > rnd.uniform(0,1):
grid[x,y] = (grid[x, y])*-1
number_of_spin_up = np.count_nonzero(grid == 1)
total_number_spin_up = np.append(total_number_spin_up,number_of_spin_up)
total_number_spin_down = np.append(total_number_spin_down, pow(N,2)-number_of_spin_up)
spin_up = total_number_spin_up[-1]
spin_down = total_number_spin_down[-1]
average_spin = (spin_up-spin_down)/N**2
return grid, average_spin
beta = 10
#runs the code to settle it.
average_spin_count = np.array([])
for i in range(300):
grid_2, average_spin = compare_energies(N**2, beta)
average_spin_count = np.append(average_spin_count, average_spin)
y = average_spin_count[-1]
I am trying to use the metropolis algorithm to simulate the Ising model. The problem that I am having is that the code will not settle all the time. For high beta values, the energy preference should be that the spins are all in the same direction, however in my code, even though it works most of the time, occasionally there will be horizontal or vertical bands of spin up and then spin down in the grid (grid2). This then makes the average spin count settle at a value which is not 1 or -1 which it should be for high beta. I have some idea where the problem lies - my delta energy at the boundary when this occurs is 4 and so at high beta this makes it really unlikely that the spin will flip and so it ends up being stuck. I was thinking that maybe I am not running it long enough but looking at the average_spin_count on the variable explorer it seems to settle after maximum 200 turns. I was also thinking maybe using diagonals but other codes and simulations of this don't seem to use this idea and so I was hoping someone could point out where I am going wrong. (You have to run the code multiple times until you get a case where there are not all spin up/down). Thanks
import numpy as np
import numpy.random as rnd
N = 20
#grid size
random_number = np.random.randint(0,1000)
prob = 0.5
#probability of starting with spin down.
np.random.seed(random_number)
grid =np.random.choice(list(range(-1, 0)) + list(range(1, 2)), size=(N, N), p=[prob,1-prob])
def find_energy(grid, r, c):
if r < N-1 and c < N-1:
energy = -((grid[r,c]*grid[r+1,c])+(grid[r,c]*grid[r-1,c])+
(grid[r,c]*grid[r,c+1])+(grid[r,c]*grid[r,c-1]))
if r == (N-1) and c < N-1:
energy = -((grid[r,c]*grid[0,c])+(grid[r,c]*grid[r-1,c])+
(grid[r,c]*grid[r,c+1])+(grid[r,c]*grid[r,c-1]))
if c == (N-1) and r < N-1:
energy = -((grid[r,c]*grid[r+1,c])+(grid[r,c]*grid[r-1,c])+
(grid[r,c]*grid[r,0])+(grid[r,c]*grid[r,c-1]))
if c== (N-1) and r==(N-1):
energy = -((grid[r,c]*grid[0,c])+(grid[r,c]*grid[r-1,c])+
(grid[r,c]*grid[r,0])+(grid[r,c]*grid[r,c-1]))
return energy
def get_coordinate():
"""Returns a random coordinate as a tuple"""
return tuple(np.random.randint(0, high=N, size=(1, 2))[0])
def probability( delta_energy, beta):
probability = np.exp(-1*beta*delta_energy)
return probability
def compare_energies(n, beta):
total_number_spin_up=np.array([])
total_number_spin_down=np.array([])
for i in range(n):
original_point = get_coordinate()
original_energy = find_energy(grid, original_point[0], original_point[1])
new_energy = original_energy * -1
delta_energy = new_energy-original_energy
x = (original_point[0])
y = (original_point[1])
if delta_energy <= 0:
grid[x,y] = grid[x, y]*-1
#flips the spin
elif delta_energy > 0:
if probability(delta_energy, beta) > rnd.uniform(0,1):
grid[x,y] = (grid[x, y])*-1
number_of_spin_up = np.count_nonzero(grid == 1)
total_number_spin_up = np.append(total_number_spin_up,number_of_spin_up)
total_number_spin_down = np.append(total_number_spin_down, pow(N,2)-number_of_spin_up)
spin_up = total_number_spin_up[-1]
spin_down = total_number_spin_down[-1]
average_spin = (spin_up-spin_down)/N**2
return grid, average_spin
beta = 10
#runs the code to settle it.
average_spin_count = np.array([])
for i in range(300):
grid_2, average_spin = compare_energies(N**2, beta)
average_spin_count = np.append(average_spin_count, average_spin)
y = average_spin_count[-1]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您绘制这种情况的最终网格,您将看到会发生什么,例如使用
matplotlib
,如下所示:您会发现空间被分成两个区域。或者,您可以按如下方式初始化网格,而不是随机数。
您会看到类似的行为。解决方案非常简单。如果计算边界处自旋翻转的能量和相应概率,您会发现能量值为 -3,导致概率为
9.76e-27
,基本上是0< /code> 对于您给定的测试版。因此,这种状态非常稳定,在 300 次迭代内您可能不会看到任何变化。
If you plot the final grid of such a case, you will see what happens, use
matplotlib
for example, see below:You will find that the space is separated in two regions. Alternatively, you can initialize your grid as follows instead of random numbers.
You will see a similar behavior. The solution is very simple. If you calculate the energy and the corresponding probability for a spin flip at the boundary, you will find an energy value of -3 leading to a probability of
9.76e-27
which is basically0
for your given beta. Therefore, this state is very stable and you will likely not see a change within 300 iterations.