Python密度图生成贝塞尔积分衍射图案,但无法停止运行

2 投票
1 回答
6049 浏览
提问于 2025-04-18 07:39

我正在尝试制作一个圆形的衍射图案,中心有一个点,周围有一系列的环。这需要用到贝塞尔积分,代码中有定义。

我遇到的问题是,代码运行得太慢了,我等了10分钟,但什么都没显示出来。我明白这是因为我的贝塞尔积分每个点有1000次迭代,有谁能帮我解决这个问题吗?

我这样做是不是正确的方向?

我正在通过马克·纽曼的《计算物理》这本书自学Python和计算物理,练习是《计算物理》第5.4题。这里有章节的链接,位于第9页。http://www-personal.umich.edu/~mejn/cp/chapters/int.pdf

这是我想要制作的图像。

同心环

我的代码:

import numpy as np
import pylab as plt
import math as mathy

#N = number of slicices 
#h = b-a/N 

def J(m,x): #Bessel Integral
    def f(theta):
        return (1/mathy.pi)*mathy.cos(m*theta - x*mathy.sin(theta)) #I replaced np. with mathy. for this line

    N = 1000
    A = 0
    a=0
    b=mathy.pi
    h = ((b-a)/N)

    for k in range(1,N,2):

        A +=  4*f(a + h*k)

    for k in range(2,N,2):

        A +=  2*f(a + h*k)

    Idx =  (h/3)*(A + f(a)+f(b))

    return Idx

def I(lmda,r): #Intensity
    k = (mathy.pi/lmda)    
    return ((J(1,k*r))/(k*r))**2

wavelength = .5        # microm meters
I0 = 1
points = 500           
sepration = 0.2  

Intensity = np.empty([points,points],np.float)

for i in range(points):
    y = sepration*i
    for j in range(points):
        x = sepration*j
        r = np.sqrt((x)**2+(y)**2)

        if r < 0.000000000001:
            Intensity[i,j]= 0.5 #this is the lim as r  -> 0, I -> 0.5
        else: 
            Intensity[i,j] = I0*I(wavelength,r)

plt.imshow(Intensity,vmax=0.01,cmap='hot')
plt.gray()
plt.show()

1 个回答

2

你的代码运行得不错——如果我把 N 从1000减到100,把图像大小(points)从500减到50的话。经过大约4秒的执行时间,我得到了下面的图像:

enter image description here

这是我用 cProfile 对你的代码进行分析后得到的结果:

$ python -m cProfile -s time bessel.py | head -n 10
         361598 function calls (359660 primitive calls) in 3.470 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   252399    2.250    0.000    2.250    0.000 bessel.py:24(f)
     2499    0.821    0.000    3.079    0.001 bessel.py:23(J)
        1    0.027    0.027    3.472    3.472 bessel.py:15(<module>)
     2499    0.015    0.000    3.093    0.001 bessel.py:45(I)
        1    0.013    0.013    0.013    0.013 backend_macosx.py:1(<module>)

看起来你的大部分执行时间都花在了 f 函数上。你可以考虑优化这个函数,或者试试用 PyPy 来运行你的代码。PyPy 在优化这类问题上表现得非常好。你需要安装他们版本的 numpy(可以查看 http://pypy.readthedocs.org/en/latest/getting-started.html#)。不过在我的机器上,PyPy 完成你的原始代码需要40秒(去掉了绘图的部分)。

编辑

我在我的系统上没有在 PyPy 中安装 plotlib,所以我把你最后的 plt 调用替换成了:

#plt.imshow(Intensity,vmax=0.01,cmap='hot')
#plt.gray()
#plt.show()
np.savetxt('bessel.txt', Intensity)

然后我创建了一个单独的程序,用普通的 Python 执行,内容是:

import numpy as np
import pylab as plt

Intensity = np.loadtxt('bessel.txt')

plt.imshow(Intensity,vmax=0.01,cmap='hot')
plt.gray()
plt.show()

这段代码生成了下面的图像,并对你的代码做了以下修改:

sepration = 0.008 # decrease separation

Intensity = np.empty([points,points],np.float)

for i in range(points):
    y = sepration*(i - points/2) # centre on image
    for j in range(points):
        x = sepration*(j - points/2)

enter image description here

撰写回答