最终,我的目标是相对于t,相对于X和相对于X,对表达式'u'(请参见代码)进行数值区分。
第一个想法是只将表达式数字记下来,为X和t提供数组(线性空间)。这导致错误“'添加'对象没有属性'cosh'”。关于此错误,我唯一了解的是它指示我应该使用sympy-functions而不是numpy-functions或其他方式。但是,使用符号表达(sympy函数)然后尝试进行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进行数值区分的方法?
答案 0 :(得分:0)
u
是sympy
表达式。 python / numpy中的U
。 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
会话进行演示。)
答案 1 :(得分:0)
SymPy和NumPy是完全独立的库。 SymPy在符号数学领域蓬勃发展,并在数学表达式的每个部分都使用自己的符号。
SymPy和NumPy唯一接触的地方是lambdify
,在那里所有内容都转换为NumPy符号,可以进行数字运算了。
函数u
不需要符号:它通过基于t
和X
的定义来获取SymPy表示形式。
差异完全发生在SymPy内部,例如diff(u, X, 3)
计算u
相对于X
的三阶导数。 simplify
有助于减小表达式的大小。但是,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()
将1D线性空间扩展到2D网格。网格在两个方向上可以具有不同数量的划分。函数示例:
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))