我有以下功能,我想用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返回与答案的顺序相似。我真的很难过,真的很感激帮助。
这是一项家庭作业,但这是一门物理课程。所以这个计算只是物理学中一个更广泛问题的一步。如果你帮助我,你不会帮我作弊:)
答案 0 :(得分:1)
根据维基百科文章Voigt profile,Voigt functions U(x,t)和V(x,t)可以用复数Faddeeva function w(z)表示:
U(x,t) + i*V(x,t) = sqrt(pi/(4*t))*w(i*z)
Voigt函数H(a,u)可以用U(x,t)表示为
H(a,u) = U(u/a, 1/(4*a**2))/(a*sqrt(pi))
(另请参阅DLMF section on Voigt functions。)
scipy
在scipy.special.wofz
中实现了Faddeeva功能。
使用它,这是Voigt函数的实现:
from __future__ import division
import numpy as np
from scipy.special import wofz
_SQRTPI = np.sqrt(np.pi)
_SQRTPI2 = _SQRTPI/2
def voigtuv(x, t):
"""
Voigt functions U(x,t) and V(x,t).
The return value is U(x,t) + 1j*V(x,t).
"""
sqrtt = np.sqrt(t)
z = (1j + x)/(2*sqrtt)
w = wofz(z) * _SQRTPI2 / sqrtt
return w
def voigth(a, u):
"""
Voigt function H(a, u).
"""
x = u/a
t = 1/(4*a**2)
voigtU = voigtuv(x, t).real
h = voigtU/(a*_SQRTPI)
return h
你说你知道当a = 0.01和u = 200时,H(a,u)的值是1.410526851411200e-007。我们可以查看:
In [109]: voigth(0.01, 200)
Out[109]: 1.41052685142231e-07
以上内容并未回答u
较大时代码无效的原因。要成功使用quad
,最好是充分了解您的被积函数。在您的情况下,当u
很大时,x = u
附近只有非常小的间隔对积分做出了重要贡献。 quad
没有检测到这一点,因此它错过了积分的很大一部分并返回了一个太小的值。
解决此问题的一种方法是使用points
的{{1}}参数,其中一个点非常接近间隔的终点。例如,我将quad
的调用更改为:
quad
有了这个改变,这就是你的函数为integ = inter.quad(lambda x: np.exp(-(np.square(u)-np.square(x))) * np.sin(2*a*(u-x)),
0, u, points=[0.999*u])
返回的内容:
voigt(0.01, 200)
我对价值In [191]: voigt(0.01, 200)
Out[191]: 1.4105268514252487e-07
没有严格的理由;这只是一个足够接近间隔结束的点,为大约200左右的0.999*u
提供合理的答案。对被积函数的进一步调查可以为您提供更好的选择。 (例如,你能找到一个关于被积函数最大值位置的解析表达式吗?如果是这样,那将比u
好得多。)
您还可以尝试调整0.999*u
和epsabs
的值,但在我的几个实验中,添加epsrel
参数产生了最大的影响。