python

时间:2018-02-21 19:24:16

标签: python sympy symbolic-math

我想看一个函数intensity(r)与空间的关系图,所以r(径向对称)。

但是,我从intensity(r) = integrate(integrand(r), (x,0,5))获得强度,其中integrand = exp(-x**2) * exp(np.pi*1j*(-x)) * besselj(0, r*x) * x

上述所有语法都使用sympy包,因此我首先定义 x,y = symbols('x r')

我正在使用符号变量,因为它似乎使视觉上更容易,将r作为变量留到最后,当我绘制它并为其指定数值时。

然而,用符号变量做那个可怕的积分似乎需要很长时间。

  • 有没有办法与符号变量进行数值积分?

  • 唯一的另一种选择是定义r先验值并找到每个值的积分吗?

1 个答案:

答案 0 :(得分:3)

除此之外:当您创建符号表达式时,请将其保持为符号。不要混合真实的浮动np.pi和复杂的浮动1j,而是使用SymPy的piI

from sympy import exp, pi, I, besselj, symbols
x, r = symbols('x r')
integrand = exp(-x**2) * exp(pi*I*(-x)) * besselj(0, r*x) * x

但是,看起来SymPy看起来不能将贝塞尔函数的乘积与exp(-x**2) * exp(pi*I*(-x))进行整合。这种情况已经发生,r被1代替,因此r的符号性质就在这一点之外。

直接回答你的问题:

  

有没有办法用符号变量进行数值积分?

没有,就像没有干水一样。这是一个矛盾。

  

唯一的另一种选择是定义r先验值并找到每个值的积分吗?

是。它可以通过SymPy(将调用mpmath)来完成:

>>> intensity = lambda r_: Integral(integrand.subs(r, r_), (x, 0, 5)).evalf()
>>> intensity(3)
0.0783849036516177 - 0.125648626220306*I

鉴于它的复杂价值,你打算如何计划这个函数还不是很清楚。也许你想绘制强度的绝对值?

无论如何,与SymPy / mpmath(纯Python)的集成对于绘图来说太慢了。使用SciPy的quad进行集成会更好。它不处理复杂的积分,所以我分别整合了真实和复杂的部分。

from scipy.integrate import quad
from scipy.special import jn
integrand = lambda x, r: np.exp(-x**2) * np.exp(np.pi*1j*(-x)) * jn(0, r*x) * x
intensity = lambda r: np.sqrt(quad(lambda x: np.real(integrand(x, r)), 0, 5)[0]**2 + quad(lambda x: np.imag(integrand(x, r)), 0, 5)[0]**2)

现在intensity(3)的评估速度比之前版本快得多。我们可以绘制它:

import matplotlib.pyplot as plt
t = np.linspace(0, 3)
plt.plot(t, np.vectorize(intensity)(t))

plot