在没有近似的情况下解决不正确的积分

时间:2015-06-11 01:07:44

标签: python scipy integration

我在python中解决这个问题时遇到了麻烦。集成的功能没有在集成的边界上定义。 我发现了一些与此相似的问题,但所有问题都是针对该问题的非常具体的回复。 我不想过多地估计积分,如果可能的话,根本不可能,因为我首先要做的就是避免近似。 有没有办法解决这个问题?

import numpy as np
from pylab import *
import scipy
from math import *
from scipy import integrate

m_Earth_air = (28.0134*0.78084)+(31.9988*0.209476)+(39.948*0.00934)+(44.00995*0.000314)+(20.183*0.00001818)+(4.0026*0.00000524)+(83.80*0.00000114)+(131.30*0.000000087)+(16.04303*0.000002)+(2.01594*0.0000005)
Tb0 = 288.15
Lb0 = -6.5
Hb0 = 0.0
def Tm_0(z):
    return Tb0+Lb0*(z-Hb0)
k = 1.38*10**-19 #cm^2.kg/s^2.K   #Boltzmann cst
mp = 1.67262177*10**-27 #kg
Rad= 637100000.0 #radius planet #cm
g0 = 980.665 #cm/s^2
def g(z):
    return (g0*((Rad/(Rad+z))**2.0))
def scale_height0(z):
    return k*Tm_0(z*10**-5)/(m_Earth_air*mp*g(z))



def functionz(z,zvar):
    return np.exp(-zvar/scale_height0(z))*((Rad+zvar)/(Rad+z))/((np.sqrt(((Rad+zvar)/(Rad+z))**2.0-1.0)))

def chapman0(z):
    return (1.0/(scale_height0(z)))*((integrate.quad(lambda zvar: functionz(z,zvar), z, np.inf))[0])

print chapman0(1000000)
print chapman0(5000000)

第一个变量和定义块很好。问题出在“functionz(z,zvar)”及其集成中。 非常感谢任何帮助!

3 个答案:

答案 0 :(得分:2)

除非你能用分析方法求解积分,否则没有办法在没有近似值的情况下解决它。这不是一个Python问题,而是一般的微积分问题,因此为什么数学类会花费很多精力来向您展示数值近似值。

如果您不希望它有太大差异,请选择一个方法快速收敛的小ε。

编辑 - 最后陈述的清晰度:

Epsilon - ɛ - 指的是通过积分边界的步长 - delta x-记住数值逼近方法都将积分切割成条子并将它们添加回来,将其视为每个条子的宽度,条子越小,近似越好。您可以在数字包中指定它们。

快速收敛的方法意味着该方法快速接近积分的真值,并且每个条子的近似误差很小。例如,黎曼和是一种天真的方法,假设每个条子是一个矩形,而梯形连接条子的开始和结束用一条线来形成一个梯形。在这2个中,梯形通常在试图考虑形状内的变化时收敛得更快。 (两者都不常用,因为大多数功能都有更好的猜测)

这两个变量都会改变计算的计算开销。通常情况下,epsilon是最昂贵的变化,因此为什么选择一种好的近似方法很重要(对于同一个epsil,某些方法可能会有一个数量级的误差)。

所有这些都取决于您的计算可以容忍多少错误。

答案 1 :(得分:1)

通常通过重新调整变量来消除可能的数值不稳定性。在您的情况下,zvar1e6开始,由于quad()中的某些实施细节,可能会导致问题。如果您将其缩放为y = zvar / z,那么整合从1开始,它似乎很适合z = 1e6

def functiony(z, y):
    return np.exp(-y*z/scale_height0(z))*(Rad+y*z)/(Rad+z) / np.sqrt(((Rad+y*z)/(Rad+z))**2.0-1.0)

def chapman0y(z):
    return (1.0/(scale_height0(z)))*((integrate.quad(lambda y: functiony(z,y), 1, np.inf))[0])

>>> print(chapman0y(1000000))

1.6217257661844094e-06

(我设置m_Earth_air = 28.8e-3 - 代码中缺少此常量,我认为它是(编辑)kg / mole中的空气摩尔质量。

至于z = 5e6scale_height0(z)是负数,它在指数下给出一个巨大的正值,使得积分在无穷大上发散。

答案 2 :(得分:0)

我遇到了类似的问题,发现SciPy quad需要您指定另一个参数epsabs=1e-1000limit=1000(步长限制),epsrel=1e1适用于我尝试过的所有内容。即在这种情况下:

def chapman0(z):    
    return (1.0/(scale_height0(z)))*((integrate.quad(lambda zvar: functionz(z,zvar), z, np.inf, limit=1000, epsabs=1e-1000, epsrel=1e1))[0])[0])
#results:
0.48529410529321887
-1.276589093231806e+21

似乎是一个高绝对误差容忍度,但对于不能快速收敛的积分,它似乎可以解决问题。只是张贴其他有类似问题的人,这篇文章已经过时了。其他软件包中的算法收敛速度更快,但我没有在SciPy中找到过。结果基于发布的代码(不是选定的答案)。