我需要对类型g(u)jn(u)进行积分,其中g(u)是不带零的平滑函数,而在Bessel函数中具有无穷零的jn(u),但出现以下错误:
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
首先,我需要将变量x更改为变量u并在新变量u中进行积分,但是函数u(x)在解析上是不可逆的,因此我需要使用插值来进行数值上的逆转换。
import numpy as np
from scipy.interpolate import InterpolatedUnivariateSpline
x = np.linspace(0.1, 100, 1000)
u = lambda x: x*np.exp(x)
dxdu_x = lambda x: 1/((1+x) * np.exp(x)) ## dxdu as function of x: not invertible
dxdu_u = InterpolatedUnivariateSpline(u(x), dxdu_x(x)) ## dxdu as function of u: change of variable
之后,积分为:
from mpmath import mp
def f(n):
integrand = lambda U: dxdu_u(U) * mp.besselj(n,U)
bjz = lambda nth: mp.besseljzero(n, nth)
return mp.quadosc(integrand, [0,mp.inf], zeros=bjz)
我使用
quadosc
中的mpmath
而不是quad
中的scipy
,因为quadosc
更适合于对快速振荡的函数(如Bessel函数)进行积分。但是,另一方面,这迫使我使用两个不同的包,scipy
通过插值计算dxdu_u
,并且mpmath
计算贝塞尔函数mp.besselj(n,U)
和乘积dxdu_u(U) * mp.bessel(n,U)
的积分,所以我怀疑两种不同软件包的混合使用会产生一些问题/冲突。所以当我做:print(f(0))
我得到了错误:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-38-ac2976a6b736> in <module>
12 return mp.quadosc(integrand, [0,mp.inf], zeros=bjz)
13
---> 14 f(0)
<ipython-input-38-ac2976a6b736> in f(n)
10 integrand = lambda U: dxdu_u(U) * mp.besselj(n,U)
11 bjz = lambda nth: mp.besseljzero(n, nth)
---> 12 return mp.quadosc(integrand, [0,mp.inf], zeros=bjz)
13
14 f(0)
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
有谁知道我该如何解决这个问题?
谢谢
最佳答案
完整的追溯(截取的部分)表明该错误出在univariatespline对象的__call__
方法中。因此,实际上的问题在于,mpmath集成例程使用其mpf
十进制小数,而scipy无法处理它们。
然后,最简单的解决方法是将integrand
参数的有问题的部分手动转换为浮点数:integrand = lambda U: dxdu_u(float(U)) * mp.besselj(n,U)
通常,这容易产生数字错误(mpmath故意使用其高精度变量!),因此请谨慎操作。在这种特定情况下,可能会没事,因为插值实际上是以双精度完成的。不过,最好检查一下结果。
一种可能的选择是避免使用mpmath并在weights
中使用scipy.integrate.quad
参数,请参见docs(向下滚动至weights="sin"
部分)
另一种选择是始终坚持使用mpmath并在纯python中实现插值(这样,mpf
对象可能很好,因为它们应该支持常用的算术)。一个简单的线性插值就足够了。如果不是这样,那么编写自己的三次样条插值器就没什么大不了的。
关于python - TypeError:根据规则“安全”,无法将数组数据从dtype('O')转换为dtype('float64'),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59652764/