将多变量函数的积分定义为第二个函数python

时间:2019-12-22 14:10:47

标签: python function scipy integration quad

将多变量函数的积分定义为第二个函数python

我正在使用python在一个变量上仅集成一个多变量函数(它是x和theta的函数,并且我正在从0到2 * pi的theta上进行积分,因此结果是x的函数)。我尝试了以下操作:

import numpy as np
import scipy.integrate as inte
d=10.0
xvals=np.linspace(-d,d,1000)
def aIntegrand(theta,x):
    return 1/(2*np.pi)*np.sin(2*np.pi*x*np.sin(theta)/d)**2
def A(x):
    return (inte.quad(aIntegrand,0,2*np.pi,args=(x,))[0])**(1/2)

plt.plot(xvals,A(xvals))
plt.xlabel("x")
plt.ylabel("A(x)")
plt.show()

,我收到以下错误消息:

TypeError: only size-1 arrays can be converted to Python scalars

我认为这是因为Quad积分器的结果是一个包含两个元素的数组,而python不喜欢基于索引数组定义函数?但这是对问题的完整猜测。如果有人知道我该如何解决并让我知道,那就太好了:)


第二次尝试

我成功使用以下代码成功获取了积分图:

import numpy as np
import scipy.integrate as inte
import matplotlib.pyplot as plt
d=10.0
xvals=np.linspace(-d,d,1000)
thetavals=np.linspace(0.0,2*np.pi,1000)
def aIntegrand(theta,x):
    return 1/(2*np.pi)*np.sin(2*np.pi*x*np.sin(theta)/d)**2
def A(x):
    result=np.zeros(len(x))
    for i in range(len(x)):
        result[i]=(inte.quad(aIntegrand,0,2*np.pi,args=(x[i],))[0])**(1/2)
    return result
def f(x,theta):
    return x**2* np.sin(theta)

plt.plot(xvals,A(xvals))
plt.xlabel("x")
plt.ylabel("A(x)")
plt.show()

Integral Plot

但这并不能提供A(x)作为函数,由于我定义它的方式,它需要数组形式的输入。我需要函数与aIntegrand的形式相同,在给定参数返回单个值的情况下,函数可以重复集成。

2 个答案:

答案 0 :(得分:1)

我认为您所寻求的东西并不存在于Scipy中。但是,您至少有两种选择。

  1. 首先,您可以使用interp1d创建一个插值器。这意味着您最初提供的x值范围决定了您可以调用内插器的范围。然后可以在此间隔内为任何x值调用此插值器。
  2. 即使您没有可赎回权,也可以执行第二个积分。函数simps仅需要值及其位置来提供对集成过程的估计。否则,您可以使用dblquad在一个呼叫中执行双重集成。

答案 1 :(得分:0)

首先请注意,您的积分可以进行解析计算。是

0.5 * (1 - J0(4 * pi * x / d))

其中J0是第一种Bessel函数。

第二,您可以使用quadpy(我的项目之一);它具有完全矢量化的计算。

import numpy as np
import quadpy
import matplotlib.pyplot as plt
import scipy.special

d = 10.0
x = np.linspace(-d, d, 1000)


def aIntegrand(theta):
    return (
        1
        / (2 * np.pi)
        * np.sin(2 * np.pi * np.multiply.outer(x, np.sin(theta)) / d) ** 2
    )


Ax2, err = quadpy.quad(aIntegrand, 0, 2 * np.pi)
Ax = np.sqrt(Ax2)

plt.plot(x, Ax, label="quadpy")
plt.xlabel("x")
plt.ylabel("A(x)")
plt.plot(x, np.sqrt(0.5 * (1 - scipy.special.jv(0, 4*np.pi*x/d))), label="bessel")
# plt.show()
plt.savefig("out.png", transparent=True, bbox_inches="tight")

enter image description here