对于我的计算物理课,我们必须计算NaCl的Madelung Constant。我执行此操作的代码使用三个嵌套for循环,因此运行速度非常慢。我想知道是否有办法使用数组或其他方法来提高计算速度。谢谢
from math import sqrt
l= int(input("The lattice size is :"))
M = 0.0
for i in range(-L,L+1):
for j in range(-L,L+1):
for k in range(-L,L+1):
if not (i==j==k==0):
M += ((-1)**(i+j+k+1))/sqrt(i*i +j*j +k*k)
print("The Madelung constant for NaCl with lattice size",l,"is",M)
答案 0 :(得分:2)
这是一种使用np.ogrid
开放网格而不是创建实际网格的方法,基于this other post
必须非常高效 -
# Create open meshes for efficiency purposes
I,J,K = np.ogrid[-L:L+1,-L:L+1,-L:L+1]
# Perform all computations using those open meshes in a vectorized manner
all_vals = ((-1)**(I+J+K+1))/np.sqrt(I**2 +J**2+ K**2)
# Corresponding to "not (i==j==k==0)", which would be satisfied by
# just one combination and that will occur at location (L,L,L),
# let's set it as zero as a means to sum later on without adding for that elem
all_vals[L,L,L] = 0
M_out = all_vals.sum()
答案 1 :(得分:1)
由于您在评论中指出您可以使用numpy
,我建议您这样做。您可以为整数构建一个3d网格,并同时计算每个项,从而对计算进行矢量化。您只需要注意每个整数为0的单数情况,例如使用numpy.where
:
import numpy as np
ran = np.arange(-L,L+1)
i,j,k = np.meshgrid(ran,ran,ran)
M = np.where((i!=0) | (j!=0) | (k!=0),
(-1)**(i+j+k+1)/np.sqrt(i**2+j**2+k**2),
0).sum()
ran
是一个numpy数组,其元素与range()
中的元素相同(如果转换为python 3中的列表)。 meshgrid
然后构造三个3d数组,它们一起跨越需要执行总和的3d空间。
请注意,对于大型域,此方法需要更高的内存。这是矢量化的一个因素:你可以节省CPU时间,但代价是增加内存需求。