Ising Model 2D Python

时间:2018-01-29 14:38:37

标签: python physics montecarlo

我已经编写了基于蒙特卡罗模拟和Metropolis算法的Ising模型模拟,但我遇到了一些麻烦,即ValueError: setting an array element with a sequence。任何帮助解决这个问题将不胜感激。

以下显示错误在代码中的位置:

The image embedded shows where the error lies in the code

如果有人发现任何可能阻止代码生成图表的其他错误,请告诉我。

# Code Mark 1.4: Ising Model in 2D

# Importing all the necessary packages I will use:
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
import numpy.random as rnd

# Before I do anything I need to make sure the specifics of the size of the lattice as a 12x12 sized, number of steps, number of temperature points used, number of points in order to reach an equilibrium state are all accounted for
num=16 
steps_monte=100
temp_points=50 
steps_equil=100 
num_a=1/(steps_monte*(num**2))
num_b=1/((steps_monte**2)*(num**2))

# Next I must create an intitial spin state for my molecule: 
def startspin(num):   
    spin=rnd.randint(2,size=(num,num))-1
    return spin

# Now I need to define the energy function. This will give the energy of any given spin state:
def Energy(Q):
    starting_energy=0
    for i in range(len(Q)):
        for j in range(len(Q)):
            g=Q[i,j]
            n_y=Q[(i+1)%num,j]+Q[i,(j+1)%num]+Q[(i-1)%num,j]+Q[i,(j-1)%num]
            starting_energy+=g*-n_y
    return starting_energy/4

# Now I need to code the Monte Carlo Steps with Metro ALgorithm for the ising model:
def montestep(Q,P):
    for i in range(num):
        for j in range(num):
                x=rnd.randint(0,num)
                y=rnd.randint(0,num)
                z=Q[x,y]
                n_y=Q[(x+1)%num,y]+Q[x,(y+1)%num]+Q[(x-1)%num,y]+Q[x,(y-1)%num]
                l=2*z*n_y
                if l<0:
                    z*=-1
                elif rnd.rand()<np.exp(P*-l):
                    z*=-1
                Q[x,y]=z
    return Q

#Now I need to define the magnetization function. This gives the Magnetization of any given spin state:
def Magnetization(Q):
    magnetization=np.sum(Q)
    return magnetization

# Here I am saying that the temperature points need to have a midpoint where we expect the disorder to begin and to give us random points between this value as 1<T<5
temp_mid = 2.25;    
Temp=rnd.normal(temp_mid,0.5,temp_points)
Temp=Temp[(Temp>1)&(Temp<5)]   
temp_points=np.size(Temp)

# I need to define 0 points for each of the 4 physical quantities I wish to find:
Magnetization=np.zeros(temp_points)
SpecificHeat=np.zeros(temp_points)  
Energy=np.zeros(temp_points)
Susceptibility=np.zeros(temp_points)

# Now I need to implement each function above by creating an Ising Function with them:
for j in range(len(Temp)):
    E_a=M_a=0
    E_b=M_b=0
    Q=startspin(num)
    init_Temp_a=1/Temp[j] 
    init_Temp_b=init_Temp_a**2

    for i in range(steps_monte):
        montestep(Q,init_Temp_a)            
        Energy_calc=Energy[Q]  
        Mag_calc=Magnetization[Q]       
        E_a=E_a+(Energy_calc)
        M_a=M_a+(Mag_calc)
        M_b=M_b+(Mag_calc**2)
        E_b=E_b+(Energy_calc**2)
        Energy[j]=num_a*E_a[i][j]
        Magnetization[j]=num_a*M_a[i][j]
        SpecificHeat[j]=(num_a*E_b[i][j]-num_b*(E_a[i][j]**2))*init_Temp_b
        Susceptibility[j]=(num_a*M_b[i][j]-num_b*(M_a[i][j]**2))*init_Temp_a

    for k in range(steps_equil):        
        montestep(Q,init_Temp_a)   

#Finally I can plot the 4 graphs I need to show the monte carlo steps of the ising model and can then conduct my research thereafter.

plt.plot(T, Energy,'d', color="#8A2BE2")
plt.xlabel("Temperature (Kelvin)")
plt.ylabel("Energy (Arbitrary Units)")
plt.show()

plt.plot(T, abs(Magnetization),'x', color="#7FFF00")
plt.xlabel("Temperature (Kelvin)")
plt.ylabel("Magnetization (Arbitrary Units)")
plt.show()

plt.plot(T, SpecificHeat, 'd', color="#00FFFF")
plt.xlabel("Temperature (Kelvin)")
plt.ylabel("Specific Heat (Arbitrary Units)")
plt.show()

plt.plot(T, Susceptibility, 'x', color="#0000FF")
plt.xlabel("Temperature (Kelvin)")
plt.ylabel("Susceptibility (Arbitrary Units)")
plt.show()

1 个答案:

答案 0 :(得分:1)

您可以通过以下方式找到此错误:

print(type(Energy[j]), type(num_a), type(E_a))

在您设置Energy[j]之前。你发现它不会起作用:

<class 'numpy.float64'> <class 'float'> <class 'numpy.ndarray'>

E_a是一个numpy数组。您无法将数组分配给必须解析为浮点数的值。我不熟悉算法,但您可能想要使用以下内容吗?

Energy[j]= num_a * E_a[i][j]

稍后设置Magnetization[j]您会发现同样的问题。同样的问题,同样的修复。

这解决了我的机器上运行Python 3.5.2的问题。但代码仍有问题。例如,num_b被引用两次但从未创建过。

编辑:将num_2重命名为num_b,将M1重命名为M_a,还有一些错误。基本上你的功能可能是这样的:

for i in range(len(Temp)):
    E_a=M_a=0
    E_b=M_b=0
    Q=startspin(num)
    init_Temp_a=1/Temp[i] 
    init_Temp_b=init_Temp_a**2

    for j in range(steps_monte):
        montestep(Q,init_Temp_a)            
        Energy_calc=Energy[Q]  
        Mag_calc=Magnetization[Q]       
        E_a=E_a+(Energy_calc)
        M_a=M_a+(Mag_calc)
        M_b=M_b+(Mag_calc**2)
        E_b=E_b+(Energy_calc**2)
        print(E_a[i][j])
        Energy[j]= num_a * E_a[i][j]
        Magnetization[j]=num_a*M_a[i][j]
        SpecificHeat[j]=(num_a*E_b[i][j]*(E_a[i][j]**2))*init_Temp_b
        Susceptibility[j]=(num_a*M_b[i][j]*(M_a[i][j]**2))*init_Temp_a

    for _ in range(steps_equil):        
        montestep(Q,init_Temp_a)   

但这显示出更多问题。看看以下内容:

for i in range(len(Temp)):
for j in range(steps_monte):

steps_monte设置为1024,Temps的长度似乎是非常数(但超过250)。所以这将迭代很多值,对吧?好吧,不是真的。因为它迭代的数组并不大。因此迭代将超出界限。该数组比迭代更早停止。

这让我想知道算法实现是否以更大的方式存在缺陷。

注意:您的代码在j之前使用i。我改变了这一点,这是一种更常见的符号,更容易理解。