Python中耦合向量场的Runge-Kutta

Python中耦合向量场的Runge-Kutta,python,simulation,physics,differential-equations,Python,Simulation,Physics,Differential Equations,我想用Python中的Runge-Kutta求解自旋晶格系统的含时海森堡运动方程。但我愿意接受任何关于如何解决这个方程的建议 从一个120°结构的三角形晶格上的N*N个经典向量系统开始(每个向量向其邻居旋转120°),通过定义一个包含(N,N,3)个条目的矩阵,仅与最近邻相互作用 通常人们会期望在自旋上做一些激发(以依赖于时间的自旋翻转的形式)会出现一些在晶格上的传播,但我看到的是到目前为止向量没有移动(或者只是一些微小的移动)。这个等式看起来像 但在我的例子中更简单一些(来源:)。我只用一个J

我想用Python中的Runge-Kutta求解自旋晶格系统的含时海森堡运动方程。但我愿意接受任何关于如何解决这个方程的建议

从一个120°结构的三角形晶格上的N*N个经典向量系统开始(每个向量向其邻居旋转120°),通过定义一个包含(N,N,3)个条目的矩阵,仅与最近邻相互作用

通常人们会期望在自旋上做一些激发(以依赖于时间的自旋翻转的形式)会出现一些在晶格上的传播,但我看到的是到目前为止向量没有移动(或者只是一些微小的移动)。这个等式看起来像 但在我的例子中更简单一些(来源:)。我只用一个J,没有磁场B。局部磁场是这个方程中的第一项:

def localField(J,S,i,j):
        n = len(S)
        h = []
        hx = - J*(S[(i - 1) % n,j][0]+S[(i + 1) % n,j][0] +S[i,(j - 1) % n][0] +S[(i - 1) % n,(j + 1) % n][0]+S[(i + 1) % n,(j - 1) % n][0] +S[i,(j + 1) %n][0]) 
        hy = - J*(S[(i - 1) % n,j][1]+S[(i + 1) % n,j][1] +S[i,(j - 1) % n][1] +S[(i - 1) % n,(j + 1) % n][1]+S[(i + 1) % n,(j - 1) % n][1] +S[i,(j + 1) %n][1])
        hz =- J*(S[(i - 1) % n,j][2]+S[(i + 1) % n,j][2] +S[i,(j - 1) % n][2] +S[(i - 1) % n,(j + 1) % n][2]+S[(i + 1) % n,(j - 1) % n][2] +S[i,(j + 1) %n][2]) 

        h.append(hx)
        h.append(hy)
        h.append(hz)
        return(h)
    def HeisenEqM2(conf,J1):
        S=np.copy(conf)
        n=len(S)
        conf_sum = np.zeros(3)
        Snew = np.zeros((n,n,3))
        locF = np.zeros(3)
        for i in range(n):
            for j in range(n):

                localFie = localField(J1,S,i,j)



                Snew[i,j] += np.cross(S[i,j],localFie)

        return(Snew)
然后,我开始在晶格的中间旋转一个旋转,并想看看波是否通过晶格传播(根据自旋波理论)。 我的想法:这是我对龙格-库塔方法的定义。最后,我规范化了我的新自旋配置,以确保向量的大小保持不变,并计算能量以查看发生了什么:

def runge_kutta_4th(S,omega,J1,Tstart,Tmax,tsteps):
    n=len(S)

    S2 = np.copy(S)
    tt = np.linspace(Tstart,Tmax,tsteps)
    dt = (Tmax-Tstart)/tsteps

    en = []
    for i in range(tsteps):

        S1 = np.copy(circ_ex(omega,tt[i],S2))
        k1 = HeisenEqM2(S1,J1)
        k2 = HeisenEqM2(circ_ex(omega,tt[i]+dt/2,S1+ dt/2*k1) ,J1) 
        k3 = HeisenEqM2(circ_ex(omega,tt[i]+dt/2,S1+ dt/2*k2)  ,J1) 
        k4 = HeisenEqM2(circ_ex(omega,tt[i]+dt,S1+ dt*k3)  ,J1) 
        S2 =S1 +  dt*(1/6*k1 + 1/3*k2 + 1/3*k3 + 1/6*k4)

        S2 = norm_rand(S2)

        en.append(JEnergy(J1,S2)/n**2)
    return(S2,en)
要复制代码:如果要复制代码,可以从以下自旋晶格系统开始:

#defining a neel lattice
def neelM(nsize):
    X=np.ones((nsize,nsize))*np.pi/2
    x= np.pi/2
    for i in range(nsize):
        for j in range(nsize):
            X[i,j] += 2*np.pi/3*(i+2*j)
    P = polar(X)
    return(P)

#returning neel lattice as XY components 
def neelMXY(M):
    n = len(M[0])
    v = np.zeros((int(n**2),3))
    X = M[0].flatten()
    Y = M[1].flatten()
    for i in range(n**2):
        v[i,0] += X[i]
        v[i,1] += Y[i]
        v[i,2] = 0
    return(v)
它叫做Neel态,是三角形海森堡反铁磁体的基态。然后,您还需要一个非常简单的自旋向量标准化:

def norm_rand(M):
    n = len(M)
    Mnew = np.zeros(np.shape(M))
    for i in range(n):
        for j in range(n):
            norm = np.linalg.norm(M[i,j])
            Mnew[i,j] += M[i,j]/norm
    return(Mnew)
为了知道你们系统的能量在哪里,我定义了海森堡能量,它是一个向量和所有相邻向量的标量积

def JEnergy(J,S):
    n=np.shape(S[1])[0]
    H=0
    counter = 0
    for i in range(n):
        for j in range(n):

            H += 1/2*J*(np.dot(S[i,j],S[(i - 1) % n,j])+np.dot(S[i,j],S[(i + 1) % n,j])+np.dot(S[i,j],S[i,(j - 1) % n])+np.dot(S[i,j],S[(i - 1) % n,(j + 1) % n])+np.dot(S[i,j],S[(i + 1) % n,(j - 1) % n])+np.dot(S[i,j],S[i,(j + 1) %n]))
            counter+=1
    return(H) 
毕竟,您可以运行以下操作:

neel24 = np.reshape(neelMXY(neelM(24)),(24,24,3))

rk24 = runge_kutta_4th(neel24,5*np.pi,1,0,10,10000)

Tt = np.linspace(0,10,10000)
list0 = []
for i in range(10000):
    list0.append(JEnergy(1,circ_ex(5*np.pi,Tt[i],iter24)))

plt.plot(np.linspace(0,10,10000),rk24[1])
plt.plot(np.linspace(0,10,10000),np.dot(list0,1/24**2))
它表明,仅仅在时间上翻转一个自旋比龙格-库塔方法有更大的影响。但事实并非如此,因为在运动方程的叉积上,一个自旋的变化也会影响到多个自旋,从而导致更高的能量变化。我还使用
quivel
绘制了矢量图,它表明矢量随时间变化不大。此图显示了能量:


如果有人能帮助我,那就太好了。这个问题应该是可以解决的,因为上面的论文做了类似的事情,但系统更复杂

这个问题可能会在新媒体上引起更多关注
neel24 = np.reshape(neelMXY(neelM(24)),(24,24,3))

rk24 = runge_kutta_4th(neel24,5*np.pi,1,0,10,10000)

Tt = np.linspace(0,10,10000)
list0 = []
for i in range(10000):
    list0.append(JEnergy(1,circ_ex(5*np.pi,Tt[i],iter24)))

plt.plot(np.linspace(0,10,10000),rk24[1])
plt.plot(np.linspace(0,10,10000),np.dot(list0,1/24**2))