使用 scipy.quad 计算难积分

计算科学 Python 正交
2021-12-15 03:23:29

使用 scipy.quad 在 python 中评估以下积分时,我收到以下警告:

用户警告:已达到最大细分数 (50)。如果增加限制没有改善,建议分析被积函数以确定困难。如果可以确定局部难度的位置(奇点、不连续性),则可能会从拆分区间并调用子范围上的积分器中获益。也许应该使用专用的积分器。

此外,真正的积分界限应该是零到无穷大(见下文),但是当我将界限更改为此时,我的结果看起来与下面示例中使用的有限值非常不同。我应该如何计算这个积分?

我有以下复杂的积分来进行数值计算:

0Re(t1(s)it2(s)ζ2(s)1)exp(iωs/V)ds

这里i=1,t1t2是实参数函数s,V=π2(π+2)是一个常数,并且ζ(s)是一个复杂的函数s. 功能t1,t2, 和ζ不是以封闭形式提供的,而是我用数字计算了它们。可以在http://speedy.sh/prG9e/stackexchange.npy下载一个 numpy 数组,其中包含在 s 的不同值处采样的函数值被积函数是有问题的,因为ζ(0)=1.

我已经绘制了各种欧米茄值的被积函数:

在此处输入图像描述

实被积函数的奇点是显而易见的。到目前为止我的工作:

import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate

T2 = np.load('stackexchange.npy') #Data: [s, x1, x2, t1, t2]

def pyfunc(z):
    return np.sqrt(z**2-1)

def integrand(s, omega):
    x1 = np.interp(s, T2[:,0], T2[:,1] )
    x2 = np.interp(s, T2[:,0], T2[:,2] )
    t1 = np.interp(s, T2[:,0], T2[:,3] )
    t2 = np.interp(s, T2[:,0], T2[:,4] )
    zeta = x2+x1*1j
    sigma = np.pi/(np.pi+2) 
    V = 1/(2*sigma) 
    return (-t2*np.real(1j/pyfunc(zeta))+t1*np.real(1/pyfunc(zeta)))*np.exp(1j*omega*s/V)


def integral(omega):
    def real_func(x,omega):
        return np.real(integrand(x,omega))
    def imag_func(x,omega):
        return np.imag(integrand(x,omega))
    a = 0.05 #Lower bound
    b = 20.0 #Upper bound
    real_integral = integrate.quad(real_func, a, b, args=(omega))
    imag_integral = integrate.quad(imag_func, a, b, args=(omega))   
    return real_integral[0] + 1j*imag_integral[0]

vintegral = np.vectorize(integral)

omega = np.linspace(-30, 30, 601)
I = integral(omega)

plt.plot(omega, I.real, omega, I.imag)
plt.show()

编辑

我找到了所讨论的被积函数的分析表示,定义如下。尽管在我尝试积分时返回了 NaN,但它似乎仍然存在一些数值困难。

    def pyfunc(z):
        return np.sqrt(z**2-1)  

    def func(theta):
        t1 = 1/np.sqrt(1+np.tan(theta)**2)    
        t2 = -1/np.sqrt(1+1/np.tan(theta)**2)
        return t1, t2


    def integrand(s, omega):
            sigma = np.pi/(np.pi+2) 
            xs = np.exp(-np.pi*s/(2*sigma))
            x1 = -2*sigma/np.pi*(np.log(xs/(1+np.sqrt(1-xs**2)))+ np.sqrt(1-xs**2))
            x2 = 1-2*sigma/np.pi*(1-xs)
            zeta = x2+x1*1j
            Vc = 1/(2*sigma)
            theta =  -1*np.arcsin(np.exp(-np.pi/(2.0*sigma)*s))
            t1, t2 = func(theta)
            return np.real((t1-1j*t2)/pyfunc(zeta))*np.exp(1j*omega*s/Vc)

    def integral(omega):
        def real_func(x,omega):
            return np.real(integrand(x,omega))
        def imag_func(x,omega):
            return np.imag(integrand(x,omega))
        a = 0
        b = np.inf
        real_integral = integrate.quad(real_func, a, b, args=(omega))
        imag_integral = integrate.quad(imag_func, a, b, args=(omega))   
        return real_integral[0] + 1j*imag_integral[0]

    vintegral = np.vectorize(integral)
0个回答
没有发现任何回复~