0

最终,我的目标是在数值上区分表达式“u”(参见代码)相对于 t、相对于 X 和相对于 X 的三倍。

第一个想法是只用数字写下表达式,为 X 和 t 提供数组(linspaces)。这导致错误“'Add' object has no attribute 'cosh'”。关于这个错误,我唯一知道的是它表明我应该使用 sympy-functions 而不是 numpy-functions 或其他方式。但是,使用符号策略表达式(sympy-functions)然后尝试lambdify 给出了同样的错误,这次没有属性'sinh'。

我不知道我哪里错了。符号表达式定义得很好,只有当我将第一个lambdify添加到代码中时才会发生错误。

import numpy as np
import sympy as sp
c_1=1.35
c_2=0.7
X = sp.Symbol('X')
t = sp.Symbol('t')
u = sp.Function('u')(X,t)
u = 2*(c_1-c_2)*(c_1*(sp.cosh(sp.sqrt(c_2)*(X-c_2*t)/2))**2 + c_2*(sp.sinh(sp.sqrt(c_1)*(-X-c_1*t)/2))**2)/((sp.sqrt(c_1)-sp.sqrt(c_2))*sp.cosh((sp.sqrt(c_1)*(-X-c_1*t) + sp.sqrt(c_2)*(X-c_2*t))/2)+ (sp.sqrt(c_1)+sp.sqrt(c_2))*sp.cosh((sp.sqrt(c_1)*(-X-c_1*t)-sp.sqrt(c_2)*(X-c_2*t))/2))**2
Y= np.linspace(-20,20,100)
T = np.linspace(-35,35,300)
U = sp.lambdify(X,u,"numpy")
U2 = sp.lambdify(t,U(Y),"numpy")(T)

有谁知道如何修复我的代码以防止此错误,或者知道另一种方法来数字区分 u,如上所述?

4

2 回答 2

1

SymPy 和 NumPy 是完全独立的库。SymPy 在符号数学的世界中蓬勃发展,并且在数学表达式的每个部分都使用自己的符号。

SymPy 和 NumPy 唯一接触的地方是lambdify所有内容都转换为 NumPy 符号,准备进行数字运算。

该函数u不需要符号:它通过基于tand的定义获得其 SymPy 表示X

微分完全发生在 SymPy 内部,例如diff(u, X, 3)计算关于 的三阶导uXsimplify有助于减小表达式的大小。但是,表达式du_dddX似乎很长,以至于简化需要大量时间。如果您不需要调用该函数数百万次,则可以不做简化。

import numpy as np
import sympy as sp
c_1 = 1.35
c_2 = 0.7
X = sp.Symbol('X', real=True)
t = sp.Symbol('t', real=True)
u = 2*(c_1-c_2)*(c_1*(sp.cosh(sp.sqrt(c_2)*(X-c_2*t)/2))**2 + c_2*(sp.sinh(sp.sqrt(c_1)*(-X-c_1*t)/2))**2)/((sp.sqrt(c_1)-sp.sqrt(c_2))*sp.cosh((sp.sqrt(c_1)*(-X-c_1*t) + sp.sqrt(c_2)*(X-c_2*t))/2)+ (sp.sqrt(c_1)+sp.sqrt(c_2))*sp.cosh((sp.sqrt(c_1)*(-X-c_1*t)-sp.sqrt(c_2)*(X-c_2*t))/2))**2
du_dt = sp.simplify(sp.diff(u, t))
du_dX = sp.simplify(sp.diff(u, X))
du_dddX = sp.diff(u, X, 3)
#du_dddX = sp.simplify(du_dddX)

U = sp.lambdify((X,t), u, "numpy")
U1 = sp.lambdify((X,t), du_dt, "numpy")
U2 = sp.lambdify((X,t), du_dX, "numpy")
U3 = sp.lambdify((X,t), du_dddX, "numpy")

# before this line, everything happened in SymPy
# now the NumPy part starts

Y = np.linspace(-20, 20, 20)
T = np.linspace(-35, 35, 20)

print(U(Y, T))
print(U1(Y, T))
print(U2(Y, T))
print(U3(Y, T))

请注意,如果要直接在它们上调用lambdified 函数,则 Y 和 T 的 linspace 需要具有相同的大小。您可能希望使用np.meshgrid(). 网格在两个方向上可以有不同数量的分割。您的功能示例:

import matplotlib.pyplot as plt
Y = np.linspace(-20, 20, 100)
T = np.linspace(-35, 35, 300)
YY, TT = np.meshgrid(Y, T)
z = U1(YY, TT)
h = plt.contourf(Y,T,z)
plt.show()

PS:将表达式转换为 LaTeX,虽然很长:

print(sp.latex(du_dt))
print(sp.latex(du_dX))
于 2019-11-07T08:37:44.610 回答
0

usympy表达。 U在 python/numpy 中。sp.sinh等被翻译成np.sinh等 。

U(Y)numpy数组计算它,但t仍然是一个符号。这会产生一个numpy对象 dtype 数组,其中包含某种数字和符号的混合。 np.sinh(x)被评估为[z.sinh() for z in x]。由于大多数对象(包括符号)都没有sinh方法,这会引发您的错误。

我不确定这一点,但我怀疑你需要同时进行lambdify两者,X并一起t评估(Y,T),而不是分两步进行。

(稍后我可能会尝试通过isympy会话来证明这一点。)

于 2019-11-06T21:24:20.993 回答