我有一对函数,分别称为numeric(x,y,z)和analytic(x,y,z),其中numeric(x,y,z)是analytic(x,y,z)的近似值。我想绘制一些轮廓图以查看这些函数在x-y平面中的外观,因此对于下面的函数,我将z = 0设置为1。然后,我尝试在网格上定义函数;
def numerical_plane(x,y):
return numerical(x, y, 0)
def analytic_plane(x,y):
R = np.sqrt(x**2+y**2)
return -G*M/(np.sqrt(R**2 + (a+np.sqrt(b**2))**2))
x = np.linspace(-20, 20, 50)
y = np.linspace(-20, 20, 50)
X, Y = np.meshgrid(x, y)
Z1 = numerical(X, Y)
Z2 = analytic(X, Y)
函数数字(x,y,z)在此问题的底部定义。
Z2正常工作,但是Z1提高
TypeError: only size-1 arrays can be converted to Python scalars
因为这是一个TypeError,所以我尝试检查numeric(1,2)返回的类型;那是一个花车。另一方面,analytic(1,2)返回numpy.float64。我试图强迫numeric(x,y)返回一个numpy.float64,但这实际上并没有帮助,所以也许我走错了路。有人知道这里出了什么问题吗?
如果您需要有关函数数值(x,y,z)的更多信息,那么我已经在此处编写了它的定义
def rho(x,y,z,M = 5e10,a = 4,b =0.8):
R = np.sqrt(x**2+y**2)
rho = ((b**2*M)/(4*np.pi))*(a*R**2+(a+3*np.sqrt(z**2+b**2))*(a+np.sqrt(z**2+b**2))**2)\
/((R**2+(a+np.sqrt(z**2+b**2))**2)**(2.5)*(z**2+b**2)**(1.5))
return rho
def numerical(x, y, z, s=0.01):
integrand = lambda xx, yy, zz: -G*rho(xx,yy,zz,M,a,b)/(np.sqrt((xx- x)**2+(yy-y)**2+(zz-z)**2+s**2))
phi = nquad(integrand, ranges = [(-np.inf, np.inf), (-np.inf, np.inf), (-np.inf, np.inf)], opts = {'epsrel' : 1e-1})[0]
return phi
它涉及调用另一个函数rho(x,y,z,...),然后在所有空间上执行积分。
这里也是完整的回溯...
TypeError Traceback (most recent call last)
<ipython-input-62-cb38a0d34db9> in <module>()
11 X, Y = np.meshgrid(x, y)
12 Z1 = analytic(X, Y)
---> 13 Z2 = numeric(X, Y)
<ipython-input-62-cb38a0d34db9> in numeric(x, y)
1 def numeric(x,y):
----> 2 return numerical_phi_MN(x, y, 0)
3
4 def analytic(x,y):
5 R = np.sqrt(x**2+y**2)
<ipython-input-43-c7e02143837e> in numerical_phi_MN(x, y, z, s)
14
15 integrand = lambda xx, yy, zz: -G*rho_MN(xx,yy,zz,M,a,b)/(np.sqrt((xx-x)**2+(yy-y)**2+(zz-z)**2+s**2))
---> 16 phi = nquad(integrand, ranges = [(-np.inf, np.inf), (-np.inf, np.inf), (-np.inf, np.inf)], opts = {'epsrel' : 1e-1})[0]
17
18 return phi
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in nquad(func, ranges, args, opts, full_output)
712 else:
713 opts = [opt if callable(opt) else _OptFunc(opt) for opt in opts]
--> 714 return _NQuad(func, ranges, opts, full_output).integrate(*args)
715
716
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in integrate(self, *args, **kwargs)
767 f = partial(self.integrate, depth=depth+1)
768 quad_r = quad(f, low, high, args=args, full_output=self.full_output,
--> 769 **opt)
770 value = quad_r[0]
771 abserr = quad_r[1]
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
321 if (weight is None):
322 retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
--> 323 points)
324 else:
325 retval = _quad_weight(func, a, b, args, full_output, epsabs, epsrel,
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
388 return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
389 else:
--> 390 return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
391 else:
392 if infbounds != 0:
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in integrate(self, *args, **kwargs)
767 f = partial(self.integrate, depth=depth+1)
768 quad_r = quad(f, low, high, args=args, full_output=self.full_output,
--> 769 **opt)
770 value = quad_r[0]
771 abserr = quad_r[1]
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
321 if (weight is None):
322 retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
--> 323 points)
324 else:
325 retval = _quad_weight(func, a, b, args, full_output, epsabs, epsrel,
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
388 return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
389 else:
--> 390 return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
391 else:
392 if infbounds != 0:
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in integrate(self, *args, **kwargs)
767 f = partial(self.integrate, depth=depth+1)
768 quad_r = quad(f, low, high, args=args, full_output=self.full_output,
--> 769 **opt)
770 value = quad_r[0]
771 abserr = quad_r[1]
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
321 if (weight is None):
322 retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
--> 323 points)
324 else:
325 retval = _quad_weight(func, a, b, args, full_output, epsabs, epsrel,
/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
388 return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
389 else:
--> 390 return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
391 else:
392 if infbounds != 0:
TypeError: only size-1 arrays can be converted to Python scalars
非常感谢
答案 0 :(得分:1)
问题在于scipy.integrate.nquad
只能集成一个(n维)函数。因此,它将始终返回单个值,而不是逐个元素地应用于多维矢量。
您可以通过使用numpy.vectorize
使函数向量化来解决此问题。但是,请注意文档中所说的内容:
提供矢量化功能主要是为了方便,而不是为了 性能。实现本质上是一个for循环。
使用此代码(以及G = 1
,M = 1
,rho_MN = rho
),它可以运行(尽管需要很长时间,但会在完成时通知您):
def numerical_plane(x, y):
return np.vectorize(numerical)(x, y, 0)