«Добавить» объект не имеет атрибута «грех» ошибка в числовом и символическом выражении? - PullRequest
0 голосов
/ 06 ноября 2019

В конечном счете, моя цель состоит в том, чтобы численно дифференцировать выражение 'u' (см. Код) относительно t, относительно X и трижды относительно X.

Первая идея состояла в том, чтобы просто написатьвыражение вниз численно, предоставляя массивы (linspaces) для X и т. Это привело к ошибке «Добавить объект не имеет атрибута« cosh »». Единственное, что я знаю об этой ошибке, это то, что она указывает, что я должен использовать sympy-функции вместо numpy-функций или наоборот. Но использование символического выражения (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)

Кто-нибудь знает, как исправить мой код, чтобы предотвратить эту ошибку, или знает другой метод для численного определениядифференцировать тебя, как я описал выше?

Ответы [ 2 ]

0 голосов
/ 07 ноября 2019

SymPy и NumPy - это совершенно разные библиотеки. SymPy процветает в мире символической математики и работает со своими собственными символами для каждой части математических выражений.

Единственное место, где SymPy и NumPy соприкасаются, это lambdify, где все преобразуется в символы NumPy, готовые кgo number crunching.

Функция u не нуждается в символе: она получает представление SymPy через свое определение, основанное на t и X.

Дифференцирование происходит полностьювнутри 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))

Обратите внимание, что интервал для Y и T должен иметь одинаковый размер, если вы хотите вызватьлямбдифицированные функции прямо на них. Возможно, вы захотите расширить линейные пространства 1D до двухмерной сетки, используя 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))
0 голосов
/ 07 ноября 2019

u - это выражение sympy. 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 сеансом.)

...