我想看一个函数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
先验值并找到每个值的积分吗?
答案 0 :(得分:3)
除此之外:当您创建符号表达式时,请将其保持为符号。不要混合真实的浮动np.pi
和复杂的浮动1j
,而是使用SymPy的pi
和I
。
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))