我正试图为我的研究项目运行一个数值积分代码。它是一个三原子系统,只受Lennard-Jones力的作用。但是r_x
变量在过程中保持为0。不幸的是,我不知道为什么。这是代码的输出:
[[ 1. 9. 15.]
[ 1. 9. 15.]
[ 1. 9. 15.]
[ 1. 9. 15.]
[ 1. 9. 15.]
[ 1. 9. 15.]
[ 1. 9. 15.]
[ 1. 9. 15.]
[ 1. 9. 15.]
[ 1. 9. 15.]]
当我检查所有变量的值时,我看到r_x
只有一个值,在这个过程中它是零
import numpy as np
np.seterr(invalid = "ignore")
m = 1
x = np.array([1, 9, 15])
y = np.array([16, 22, 26])
def GetLJForce(r, epsilon, sigma):
return 48 * epsilon * np.power(sigma, 12) / np.power(r, 13) - 24 * epsilon * np.power(sigma, 6) / np.power(r, 7)
def GetAcc(xPositions, yPositions):
global xAcc
global yAcc
xAcc = np.zeros((xPositions.size, xPositions.size), dtype=object)
yAcc = np.zeros((xPositions.size, xPositions.size), dtype=object)
for i in range(0, xPositions.shape[0]-1):
for j in range(i+1, xPositions.shape[0]-1):
global r_x
r_x = xPositions[j] - xPositions[i]
r_y = yPositions[j] - yPositions[i]
global rmag
rmag = np.sqrt(r_x*r_x + r_y*r_y)
if(rmag[0]==0 or rmag[1]==0 or rmag[2]==0):
rmag += 1
force_scalar = GetLJForce(rmag, 0.84, 2.56)
force_x = force_scalar * r_x / rmag
force_y = force_scalar * r_y / rmag
xAcc[i,j] = force_x / m
xAcc[j,i] = - force_x / m
yAcc[i,j] = force_y / m
yAcc[j,i] = - force_y / m
else:
force_scalar = GetLJForce(rmag, 0.84, 2.56)
force_x = force_scalar * r_x / rmag
force_y = force_scalar * r_y / rmag
xAcc[i,j] = force_x / m
xAcc[j,i] = - force_x / m
yAcc[i,j] = force_y / m
yAcc[j,i] = - force_y / m
return np.sum(xAcc), np.sum(yAcc)
def UpdatexPos(x, v_x, a_x, dt):
return x + v_x*dt + 0.5*a_x*dt*dt
def UpdateyPos(y, v_y, a_y, dt):
return y + v_y*dt + 0.5*a_y*dt*dt
def UpdatexVel(v_x, a_x, a1_x, dt):
return v_x + 0.5*(a_x + a1_x)*dt
def UpdateyVel(v_y, a_y, a1_y, dt):
return v_y + 0.5*(a_y + a1_y)*dt
def RunMD(dt, number_of_steps, x, y):
global xPositions
global yPositions
xPositions = np.zeros((number_of_steps, 3))
yPositions = np.zeros((number_of_steps, 3))
v_x = 0
v_y = 0
a_x = GetAcc(xPositions, yPositions)[0]
a_y = GetAcc(xPositions, yPositions)[1]
for i in range(number_of_steps):
x = UpdatexPos(x, v_x, a_x, dt)
y = UpdateyPos(y, v_y, a_y, dt)
a1_x = GetAcc(xPositions, yPositions)[0]
a1_y = GetAcc(xPositions, yPositions)[1]
v_x = UpdatexVel(v_x, a_x, a1_x, dt)
v_y = UpdateyVel(v_y, a_y, a1_y, dt)
a_x = np.array(a1_x)
a_y = np.array(a1_y)
xPositions[i, :] = x
yPositions[i, :] = y
return xPositions, yPositions
sim_xpos = RunMD(0.1, 10, x, y)[0]
sim_ypos = RunMD(0.1, 10, x, y)[1]
print(sim_xpos)
你的代码有一些细节,它没有运行的主要原因是因为这一行
关于代码的详细信息return np.sum(xAcc), np.sum(yAcc)
,你从所有粒子之间的相互作用计算了一个加速度矩阵,其中你添加了一个粒子的加速度和另一个粒子的加速度的倒数,因为所有粒子的质量都一样,那么加速度也一样,那么你把矩阵的所有元素求和,所有的项都抵消掉了,而不是返回每个粒子的加速度,你返回所有粒子的加速度之和,假设它们都有相同的质量,那么它们的加速度之和就是0,即使它不是0,也可能是错误的,因为你把它们都混合在一起,所以所有的粒子都会有相同的加速度,朝着相同的方向运动在同样的功能中,你也有一些可以改进的东西,比如
这与
因为
B_statement
总是会被执行您不必在使用它的变量上使用
global
,在使用它们的地方它们仍然在范围内,基本上在您将在其他函数中使用该变量时使用它,基本上所有具有相同数量表格或更多表格的对象都知道该变量,这在第一行结束,比那一行少列表,这导致了下一点没有必要使这两个函数完全相同,唯一的区别是名称,它们是相同的,当您结束函数体时,函数参数的名称超出范围,因此您可以对x和y重复使用单个函数
一些例子
当我们将a用于
x
时,它不在作用域中,它只存在于fun
的主体中,因此您可以将该名称用于其他变量或参数发生这种情况的原因是a被同名的函数参数遮挡,而
因为当
fun()
查找一个变量时,它在其作用域中找不到它,所以它会查找更高的作用域,并找到一个变量a
,该变量包含值1
这是更小的,但是python有
tuples
,所以这段代码重复了RunMD
的计算(您不需要),可以简化为其中
RunMD
返回的对被分配到该对(python的两个元素的元组)sim_xpos
和sim_ypos
如果我想重写部分代码,我会删除numpy来测试算法,然后使用numpy来对操作进行矢量化,使代码更加高效,它看起来像这样
我不知道分子动力学的物理原理是否正确,当我在物理系时,我只对动力学系统进行了模拟,也许我的方法对你的系统来说过于精确或经典,你可以用它来比较
相关问题 更多 >
编程相关推荐