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