Python 不近似求解广义积分

Python 不近似求解广义积分,python,scipy,integration,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

我在用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)”及其集成。
非常感谢任何帮助

除非你能解析地解出积分,否则如果没有对其边界的近似,就无法解出它。这不是一个Python问题,而是一个一般的微积分问题,因此为什么数学课要花这么大的力气向您展示数值近似

如果你不想让它有太大的不同,选择一个小ε和一个收敛速度快的方法

编辑-上一条语句的清晰度:

ε-ɛ-指通过积分边界的步长-δx-请记住,数值近似方法都将积分切片成碎片,并将其重新相加,将其视为每个碎片的宽度,碎片越小,近似效果越好。您可以在数字包中指定这些

一种快速收敛的方法意味着该方法能够快速逼近积分的真值,并且每一条的近似误差很小。例如,Riemann和是一种简单的方法,它假设每个条子都是矩形,而梯形用一条线连接条子的起点和终点,形成梯形。在这两种情况中,梯形通常收敛得更快,因为它试图解释形状内的变化。(这两种方法都不常用,因为大多数函数都有更好的猜测)

这两个变量都会改变计算的计算费用。通常,ε是最昂贵的改变,因此,选择一个好的近似方法很重要(对于相同的ε,有些方法的误差可能相差一个数量级)


所有这些都取决于你的计算能容忍多少误差。

通过重新调整变量的大小,通常有助于消除可能的数值不稳定性。在您的情况下,
zvar
1e6
开始,由于
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=5e6
scale\u height0(z)
为负值,在指数下给出了一个巨大的正值,使得积分在无穷远处发散。

我有一个类似的问题,发现SciPy quad需要您指定另一个参数,
epsabs=1e-1000
limit=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中没有发现。结果基于发布的代码(而不是选定的答案)。

您是否希望SciPy以分析的方式解决此问题?它不会那样做;
scipy.integrate
例程都计算数值近似值。
m_Earth_air
的值是多少?当你说“选择一个小epsilon,用一个快速收敛的方法”时,你在想什么方法?即使它现在给出了一个值,问题仍然是当y=1.0时函数(z,y)是无限的,当y=inf时为nan。因此,积分的值比它应该的值小得多。注:你的比例高度0(z)是正确的,我实际上在不同的z范围内有不同的比例高度函数,比例高度0(z)只适用于11公里(我的单位是11e5)。Ps2。很好的猜测为m_Earth_air!它是28.8 kg/kmol,空气的平均分子量:)
quad()
在积分收敛时没有无穷大的问题。您可以尝试将
exp(-x)/sqrt(x)
0
集成到
inf
,您将得到
sqrt(pi)
。积分也没有什么不合适的地方。你怎么知道这个值比它应该的小?Wolframalpha毫无问题地集成了它,并给出了相同的答案。