计算马德隆常数

计算科学 Python
2021-12-06 17:41:16

通过 Mark Newmans 的书 Computational Physics 自学 Python 和计算物理学,练习是计算物理学的 2.9 我必须计算马德隆常数在此处输入图像描述.

我有两个不同的解决方案我想知道哪个代码是正确的,有没有办法在我的范围内排除0,所以我不必编写两个单独的 for 循环。我认为我的第二个答案是正确的,有人可以验证。

我的第一个答案:

M = 0

for i in range(-200,0):
    for j in range(-200,0):
        for k in range(-200,0):

            M += ((-1)**(i+j+k))/((i**2 + j**2 + k**2)**(1/2))

print(M)           
for i in range(1,200):
    for j in range(1,200):
        for k in range(1,200):

            M += ((-1)**(i+j+k))/((i**2 + j**2 + k**2)**(1/2)) 

print(M)

我的第二个回答:

M = 0
i = 0
j = 0
k = 0
for l in range(-200,0):
    i = l
    j = l
    k = l
    M += ((-1)**(i+j+k))/((i**2 + j**2 + k**2)**(1/2))

print(M)

for l in range(1,200):
    i = l
    j = l
    k = l
    M += ((-1)**(i+j+k))/((i**2 + j**2 + k**2)**(1/2))

print(M)
4个回答

下面是您可以编写的那种循环的代码(不过是用 C 语言):

  for (int n = 1; n <= L; n++) {
    for (int i = -n; i <= n; i++) {
      for (int j = -n; j <= n; j++) {
        for (int k = -n; k <= n; k++) {
          if (abs(i) != n && abs(j) != n && abs(k) != n)
            continue;

          // Your update to the potential energy goes here.
        }
      }
    }
  }

观察到这个循环迭代了半径为的立方壳。这是正确计算马德隆常数的方法(详见 [1] 的第 III 节)。n

[1] Borwein, D., Borwein, JM, & Taylor, KF (1985)。格和和马德隆常数的收敛。数学物理杂志, 26(11), 2999. doi:10.1063/1.526675

两者之间存在巨大而明显的差异。

第一个循环遍历负值的i, j, k每个组合,以及正值的每个组合i, j, k第二个只循环i == j == k值。因此,例如,第一个具有-200, -200, -200, then -200, -200, -199, 以此类推-200, -200, -1, then -200, -199, -200, 以此类推;第二个只是从-200, -200, -200-199, -199, -199

但我不知道哪个是正确的或如何验证它,因为这是一个物理问题,而不是 Python 问题。


同时,其中隐藏了一个 Python 问题:

有没有办法在我的范围内排除 0 所以我不必编写两个单独的 for 循环。

当然。range(-200, 0)您想要对 in 中的所有值和 in 中的所有值进行迭代range(1, 200)您可以chain通过将两个可迭代对象组合在一起来做到这一点:

import itertools

for i in itertools.chain(range(-200, 0), range(1, 200)):
    print(i)

或者,如果您愿意,只需手动合并它们并明确跳过 0:

for i in range(-200, 200):
    if i == 0:
        continue
    print(i)

顺便说一句,你确定你想要range(1, 200),不是range(1, 201)吗?-200在值集中似乎很奇怪,但事实200并非如此。但也许这是正确的。

我正在通过同一本书自学 Python。我的工作代码是:

from math import *
from numpy import *


M = 0.0 #set a float variable for Madelung Constant
L = int(input("Enter the size of the crystal lattice L/2: "))

for x in range(-L, L+1):
  for y in range(-L, L+1):
      for z in range(-L, L+1):
          if x == y == z == 0:
              continue
          r = (x**2 + y**2 + z**2)**-0.5
          if x + y + z%2 == 0:
            M = M+r
          else:
            M = M-r
          print(x, y, z)
print(M)

尝试这个 :)

from math import sqrt,pi

e = 1.602e-19 #Coloumbs
epsNaught = 8.85e-12 #F/m
M = 0 #Madelung constant, total potential felt by origin sodium atom
n = 0 #Number of atoms

#lattice size
L = int(input("Enter lattice size: "))

#spacing of atoms
a = int(input("Distance between atoms: "))

for i in range(-L,L+1):
    for j in range(-L,L+1):
        for k in range(-L,L+1):
            n += 1
            distance = a * sqrt(i**2 + j**2 + k**2)

            if (i == j == k == 0): #Case for soidium atom at origin
                continue

            potential = e / (4 * pi * epsNaught * distance)

            if (i+j+k)%2 == 1: #Odd, chlorine atoms, attraction = neg potential
                potential *= -1

            M += potential

print("Madelung constant:",M,"due to",n-1,"atoms.")`