我想计算整数晶格中从中心到所有其他位置的距离以及每个距离的位置数。我目前正在使用以下代码来计算这一点:
x = numpy.arange(-10, 11, 1)
[X, Y] = numpy.meshgrid(x, x)
R = numpy.sqrt(X**2+Y**2)
R2 = numpy.ndarray.flatten(R)
R3 = numpy.unique(R2)
r = R3[1:] # excludes the 0
Nr = numpy.zeros(numpy.size(r))
for i in range(numpy.size(r)):
Nr[i] = numpy.count_nonzero(R2 == r[i]
这告诉我可能的距离是 1、sqrt2、2、sqrt5 等,
它还告诉我有 4x1、4xsqrt2、4x2、8xsqrt5 等。
由于这是物理学中的常见问题,我想知道是否有来自函数的函数,例如numpy或scipy,可以更轻松地返回这些值。
晶格以(0,0)
为中心。所以它在四个象限上是对称的。因此,我们可以利用此限制来发挥自己的优势,因为我们可以计算一个象限所需的唯一距离和计数,并将这些计数乘以4
以模拟所有四个象限。
因此,假设我们使用第一象限(右上角四边形)。我们将跳过(y = 0)
线上的元素,因为否则乘以4
在所有四个象限上进行模拟将导致结果重复。此外,这样我们就不必像在原始帖子中那样排除第一个元素。
因此,实现将是 -
N = 11 # Lattice size
xa, ya = np.ogrid[0:N,1:N] # x's:0:N, y's:1:N
unq_dists, count = np.unique(np.sqrt(xa**2 + ya**2), return_counts=1)
count = count*4
为了进一步提高性能,我们可以对平方和使用np.unique
,然后在唯一求和上使用np.sqrt
。这个想法是在较小的唯一集合上执行慢速平方根计算,如下所示 -
unq_dists, count = np.unique(xa**2 + ya**2, return_counts=1)
unq_dists = np.sqrt(unq_dists)
扁平化数组后,将其转换为 PandasSeries
并计算唯一值:
distances = pandas.Series(numpy.ndarray.flatten(R))
distances.value_counts()
# 9.219544 16
# 8.062258 16
# 5.000000 12
#10.000000 12
# 7.071068 12
# 2.236068 8
# ....
可以通过几种方式提高代码的效率。您首先形成两个大矩阵,然后对项进行平方。最好先平方。此外,仅为了执行外部添加而形成网格网格是不必要的:有numpy.add.outer
。最后,您拥有的循环因numpy.unique
中的return_counts=True
选项而变得不必要。(顺便说一下,这会展平数组本身,因此您不必这样做。因此,代码缩短为三行。
x = numpy.arange(-10, 11, 1)
R = numpy.sqrt(numpy.add.outer(x**2, x**2))
r, Nr = numpy.unique(R, return_counts=True)
(如果要排除 0 距离,则返回r[1:]
和Nr[1:]
)