我有下面的函数,我想用python进行数值积分
使用scipy,我编写了以下代码:
def voigt(a,u):
fi = 1
er = Cerfc(a)*np.exp(np.square(a))
c1 = np.exp(-np.square(u))*np.cos(2*a*u)
c1 = c1*er #first constant term
pis = np.sqrt(np.pi)
c2 = 2./pis #second constant term
integ = inter.quad(lambda x: np.exp(-(np.square(u)-
np.square(x)))*np.sin(2*a*(u-x)), 0, u)
print integ
ing = c1+c2*integ[0]
return ing
对于Cerfc(a)函数,我只使用scipy.erfc公司计算互补误差函数。
所以这个函数对于u的值很小,但是大的u值(超过60 ish)会破坏代码,并且会得到非常小的数字。例如,如果输入a=0.01和u=200,结果是1.134335928072937e-40,其中真实答案是:1.410526851411200e−007
除此之外,四元计算的错误scipy返回与答案的顺序相似。我真的很为难你,我真的很感激你的帮助。
这是家庭作业,但这是物理课。所以这个计算只是物理学中更广泛问题的一个步骤。如果你帮我,你就不会帮我作弊了:)
根据维基百科文章Voigt profile,Voigt functions U(x,t)和V(x,t)可以用络合物Faddeeva functionw(z)表示:
Voigt函数H(a,u)可以用u(x,t)表示为
^{pr2}$(另请参见DLMF section on Voigt functions。)
scipy
在^{你说过当a=0.01,u=200时,H(a,u)的值是1.410526851411200e−007。我们可以检查:
上面没有回答当
u
很大时,代码为什么不能工作的问题。要成功地使用quad
,最好对被积函数有一个很好的理解。在您的例子中,当u
很大时,只有x = u
附近的一个很小的区间对积分有很大的贡献。quad
没有检测到这一点,因此它忽略了整数的大部分,并返回一个太小的值。在解决此问题的一种方法是使用
quad
的points
参数,该点非常接近间隔的终点。例如,我将quad
的调用改为:在这种变化下,函数返回
voigt(0.01, 200)
:对于值
0.999*u
,我没有一个严格的理由;这仅仅是一个距离间隔末尾足够近的点,可以对大约200左右的u
给出一个合理的答案。进一步研究被积函数可以给你一个更好的选择。(例如,你能找到被积函数最大值位置的解析表达式吗?如果是这样,那将比0.999*u
好得多您也可以尝试调整
epsabs
和epsrel
的值,但是在我的几个实验中,添加points
参数产生了最大的影响。在相关问题 更多 >
编程相关推荐