Решение системы дифференциальных уравнений 2-го порядка из симпы - PullRequest
1 голос
/ 05 апреля 2020

Я занимаюсь многократной задачей динамики DOF, используя уравнения Лагранжа 2-го порядка. Я использовал sympy, чтобы добраться до уравнений движения. Теперь эти уравнения после вычисления производных стали довольно длинными, хотя, похоже, что упрощение не может упростить его далее. Моя проблема на самом деле заключается в том, как решить эту систему из трех од ой порядка отсюда. Я не знаю, как преобразовать эти уравнения, чтобы их можно было использовать с scipy.odeint (). Подставка пришла на ум, но символов много. Поэтому я ищу phi0, phi1 и phi2, а также их первую и вторую производные. Все начальные условия: phi [0] = 0 и все dphi [0] = 0. Я надеюсь, что есть способ решить эту проблему, не выходя с нуля. Заранее спасибо.

def derivativeLagranga(Lagrange,n):
"""left side of lagrange"""
f0 = sym.Function('f0')(t)
f1 = sym.Function('f1')(t)
f2 = sym.Function('f2')(t)
f3 = sym.Function('f3')(t)
L_i = []
L_it = []
L_j =[]
L_leva = []
x=0
y=0
for i in range(0,n-1):
    x = Lagrange.diff(kot[i].diff(t))
    L_i.append(x)
for i in range(0,n-1):
    x = L_i[i].diff(t)
    x = x.replace(sym.sin(kot[i]),kot[i])
    L_it.append(x)
for i in range(0,n-1):
    x = L.diff(kot[i])
    L_j.append(x)

for i in range(0,n-1):
    x = L_it[i]+L_j[i]
    L_leva.append(x)



return L_left

left_side_L = derivativeLagranga(Lagrange, n)

f0 = sym.simplify(left_side_L[0].subs(values))
f1 = leva_stran_L[1].subs(values)
f2 = leva_stran_L[2].subs(values)

f0

Таким образом, мой f0 является одним из уравнений, я не смог скопировать вывод, поэтому я опубликую изображение.

54.51345(−(????0(?)+????1(?)−????2(?))sin(?0(?)+?1(?)−?2(?))+2.0?0(?)????0(?))(0.5(????0(?)+????1(?)−????2(?))cos(?0(?)+?1(?)−?2(?))−1.0cos(?0(?))????0(?)−1.0cos(?1(?))????1(?)+1.0cos(?2(?))????2(?))+54.51345((????0(?)+????1(?)−????2(?))cos(?0(?)+?1(?)−?2(?))+cos(?0(?))????0(?))(0.5(????0(?)+????1(?)−????2(?))sin(?0(?)+?1(?)−?2(?))+0.5?0(?)????0(?)+0.5sin(?1(?))????1(?)+1.0sin(?2(?))????2(?))+54.51345(2.0(????0(?)+????1(?)−????2(?))cos(?0(?)+?1(?)−?2(?))+cos(?0(?))????0(?))(1.0(????0(?)+????1(?)−????2(?))sin(?0(?)+?1(?)−?2(?))+0.5?0(?)????0(?)+0.5sin(?1(?))????1(?)+1.0sin(?2(?))????2(?)+0.5sin(?4(?))????4(?))−54.51345(2.0cos(?0(?))????0(?)+1.0cos(?1(?))????1(?))?0(?)????0(?)+54.51345(?0(?)+sin(?0(?)+?1(?)−?2(?)))((0.5????0(?)+0.5????1(?)−0.5????2(?))(????0(?)+????1(?)−????2(?))cos(?0(?)+?1(?)−?2(?))+(0.5?2??2?0(?)+0.5?2??2?1(?)−0.5?2??2?2(?))sin(?0(?)+?1(?)−?2(?))+0.5?0(?)?2??2?0(?)+0.5sin(?1(?))?2??2?1(?)+1.0sin(?2(?))?2??2?2(?)+0.5cos(?0(?))(????0(?))2+0.5cos(?1(?))(????1(?))2+1.0cos(?2(?))(????2(?))2)+54.51345(?0(?)+2.0sin(?0(?)+?1(?)−?2(?)))((????0(?)+????1(?)−????2(?))(1.0????0(?)+1.0????1(?)−1.0????2(?))cos(?0(?)+?1(?)−?2(?))+(1.0?2??2?0(?)+1.0?2??2?1(?)−1.0?2??2?2(?))sin(?0(?)+?1(?)−?2(?))+0.5?0(?)?2??2?0(?)+0.5sin(?1(?))?2??2?1(?)+1.0sin(?2(?))?2??2?2(?)+0.5sin(?4(?))?2??2?4(?)+0.5cos(?0(?))(????0(?))2+0.5cos(?1(?))(????1(?))2+1.0cos(?2(?))(????2(?))2+0.5cos(?4(?))(????4(?))2)+54.51345(cos(?0(?)+?1(?)−?2(?))−2.0cos(?0(?)))(−(0.5????0(?)+0.5????1(?)−0.5????2(?))(????0(?)+????1(?)−????2(?))sin(?0(?)+?1(?)−?2(?))+(0.5?2??2?0(?)+0.5?2??2?1(?)−0.5?2??2?2(?))cos(?0(?)+?1(?)−?2(?))+1.0?0(?)(????0(?))2+1.0sin(?1(?))(????1(?))2−1.0sin(?2(?))(????2(?))2−1.0cos(?0(?))?2??2?0(?)−1.0cos(?1(?))?2??2?1(?)+1.0cos(?2(?))?2??2?2(?))+54.51345(0.5?0(?)????0(?)+0.5sin(?1(?))????1(?)+0.5sin(?2(?))????2(?))cos(?0(?))????0(?)−54.51345(2.0cos(?0(?))????0(?)+2.0cos(?1(?))????1(?)−1.0cos(?2(?))????2(?))?0(?)????0(?)+54.51345(−2.0?0(?)(????0(?))2−1.0sin(?1(?))(????1(?))2+2.0cos(?0(?))?2??2?0(?)+1.0cos(?1(?))?2??2?1(?))cos(?0(?))+54.51345(−2.0?0(?)(????0(?))2−2.0sin(?1(?))(????1(?))2+1.0sin(?2(?))(????2(?))2+2.0cos(?0(?))?2??2?0(?)+2.0cos(?1(?))?2??2?1(?)−1.0cos(?2(?))?2??2?2(?))cos(?0(?))+54.51345(0.5?0(?)?2??2?0(?)+0.5sin(?1(?))?2??2?1(?)+0.5sin(?2(?))?2??2?2(?)+0.5cos(?0(?))(????0(?))2+0.5cos(?1(?))(????1(?))2+0.5cos(?2(?))(????2(?))2)?0(?)−2123.406????0(?)+45.427875?2??2?0(?)−2123.406????1(?)+9.085575?2??2?1(?)−9.085575?2??2?2(?)

И вывод lambdify:

NameError                                 Traceback (most recent call last)
<ipython-input-14-ee077b324a2e> in <module>
      2 en2 = sym.lambdify([kot_0,kot_1,kot_2],f1)
      3 en3 = sym.lambdify([kot_0,kot_1,kot_2],f2)
----> 4 en1(kot_0,kot_1,kot_2)
      5 
      6 

<lambdifygenerated-4> in _lambdifygenerated(_Dummy_227, _Dummy_226, _Dummy_225)
      9   # Derivative
     10   # Derivative
---> 11 22.722525*_Dummy_227**2*Derivative(_Dummy_227, (t, 2)) + 90.8901*_Dummy_227*(-0.5*cos(_Dummy_226)*Derivative(_Dummy_226, t) - 1.0*cos(_Dummy_227)*Derivative(_Dummy_227, t))*Derivative(_Dummy_227, t) + 90.8901*_Dummy_227*(0.5*cos(_Dummy_225)*Derivative(_Dummy_225, t) - 1.0*cos(_Dummy_226)*Derivative(_Dummy_226, t) - 1.0*cos(_Dummy_227)*Derivative(_Dummy_227, t))*Derivative(_Dummy_227, t) - 22.722525*_Dummy_227*(-_Dummy_227*Derivative(_Dummy_227, (t, 2)) - sin(_Dummy_225)*Derivative(_Dummy_225, (t, 2)) - sin(_Dummy_226)*Derivative(_Dummy_226, (t, 2)) - cos(_Dummy_225)*Derivative(_Dummy_225, t)**2 - cos(_Dummy_226)*Derivative(_Dummy_226, t)**2 - cos(_Dummy_227)*Derivative(_Dummy_227, t)**2) + 0.5*Jm*(-2*Derivative(_Dummy_225, (t, 2)) + 2*Derivative(_Dummy_226, (t, 2)) + 2*Derivative(_Dummy_227, (t, 2))) + 1.0*Jm*Derivative(_Dummy_227, (t, 2)) + 45.44505*(-1.0*_Dummy_227 - 2.0*sin(-_Dummy_225 + _Dummy_226 + _Dummy_227))*(-0.5*_Dummy_227*Derivative(_Dummy_227, (t, 2)) + (-Derivative(_Dummy_225, t) + Derivative(_Dummy_226, t) + Derivative(_Dummy_227, t))*(1.0*Derivative(_Dummy_225, t) - 1.0*Derivative(_Dummy_226, t) - 1.0*Derivative(_Dummy_227, t))*cos(-_Dummy_225 + _Dummy_226 + _Dummy_227) + (1.0*Derivative(_Dummy_225, (t, 2)) - 1.0*Derivative(_Dummy_226, (t, 2)) - 1.0*Derivative(_Dummy_227, (t, 2)))*sin(-_Dummy_225 + _Dummy_226 + _Dummy_227) - 1.0*sin(_Dummy_225)*Derivative(_Dummy_225, (t, 2)) - 0.5*sin(_Dummy_226)*Derivative(_Dummy_226, (t, 2)) - 0.5*sin(varphi_4(t))*Der

https://imgur.com/a/2UOW0NR

EDIT2: Так что после некоторого упрощения я кое-как получил 3 обыкновенные дифференциальные уравнения. Но они в симпатичной форме, как я могу решить их численно?

−800000.0?0+800000.0?2−1770.174?˙0+242.3736?¨0−1770.174?˙1+166.63185?¨1−75.74175?¨2+4245.8661 

−1200000.0?1+400000.0?2−1770.174?˙0+166.63185?¨0−1770.174?˙1+151.4835?¨1−75.74175?¨2+2830.5774 

800000.0?0+400000.0?1−2000000.0?2−75.74175?¨0−75.74175?¨1+60.5934?¨2−1415.2887

1 Ответ

0 голосов
/ 07 апреля 2020

Я представлю выполнение формализма Эйлера-Лагранжа для примера двойного маятника как нетривиальный, полный, стандартный пример, и это без использования специализированных функций в sympy.physics, только с использованием basi c средства дифференциации и написания кода от sympy. Надеемся, что он достаточно общий, так как вторая часть должна быть независимой от проблем и, следовательно, также непосредственно применимой к вашей ситуации.

from sympy import sin, cos, Symbol, symbols, solve
from sympy.utilities.lambdify import lambdify

Лагранжиан для физической модели

Сначала физическая установка для Лагранжиан использует два угла в качестве основных зависимых функций и строит кинетику c и потенциальную энергию через декартовы координаты.

# Symbols for the parameters of the problem
t,m1,m2,l1,l2,g = symbols("t,m_1 m_2 l_1 l_2 g")
# Variables of the problem
th1, th2 = Function("θ_1")(t), Function("θ_2")(t)
x1,y1 = l1*sin(th1), -l1*cos(th1)
x2,y2 = x1+l2*sin(th2), y1-l2*cos(th2)

# kinetic energy
vx1,vy1,vx2,vy2 = ( xx.diff(t) for xx in (x1,y1,x2,y2))
K1 = m1/2*(vx1**2+vy1**2)
K2 = m2/2*(vx2**2+vy2**2)
K = K1+K2
# potential energy
V = g*(m1*y1+m2*y2)
# Lagrangian
L = K - V
L = L.expand().simplify()

Чтобы получить абстрактную обработку, используйте массивы абстрактных параметров и векторы координат

params = [m1, l1, m2, l2, g]
q = [th1, th2]
dotq = [ qq.diff(t) for qq in q]

От Эйлера-Лагранжа до системы ОДУ первого порядка

В полученных выражениях становится довольно грязно, если перейти ко вторым производным от углов, можно получить более структурированный подход и, надеюсь, соответственно более быстрая оценка с использованием импульсных переменных

pk = diff(L, dotqk)
d(pk)/dt = diff(L, qk)

, где первое соотношение рассматривается как система уравнений для вычисления dotq из p.

Подготовьте новые переменные, приготовьтесь заменить функциональные символы простыми переменными.

N = len(q)
p = [ Symbol(f"p_{k+1}") for k in range(N)]
dotq_func, dotq = dotq,  [ Symbol(f"Dq_{k+1}") for k in range(N)]
q_func, q = q, [ Symbol(f"q_{k+1}") for k in range(N)]

Теперь замените все функциональные члены простыми переменными

L=L.subs(list(zip(dotq_func, dotq))).subs(list(zip(q_func, q)))

enter image description here

Теперь устанавливается sh функция для вычисления dotq из q,p

p_eqns = [ p[k] - L.diff(dotq[k]) for k in range(N)]
dotq_expr = solve(p_eqns, dotq)
dotq_func = lambdify([*q, *p, *params],[ dotq_expr[dq] for dq in dotq])

Далее генерируется функция, которая вычисляет производные p

dotp_expr = [ L.diff(q[k]) for k in range(N)]
dotp_func = lambdify([*q,*dotq,*params],dotp_expr)

Теперь соберите сгенерированные функции в полную функцию ODE и решите с ней тестовую задачу, чтобы убедиться, что она работает

def odefunc(t,u,args):
    q, p = u[:N], u[N:]
    dotq = dotq_func(*q, *p, *args)
    dotp = dotp_func(*q, *dotq, *args)
    return [*dotq, *dotp]

Подтверждение с помощью численного решения

myparams = [1,10,5,5,9.81]
t = np.linspace(0,25,301)

u = odeint(odefunc,[2,1.2, 0,0],t,args=(myparams,), tfirst=True)

%matplotlib inline
plt.figure(figsize=(8,5))
plt.plot(t,u[:,0],t,u[:,1]); 
plt.grid(); plt.show()

В результате получается следующий график для функций угла enter image description here

Outlook

Можно ожидать даже более высокой производительности, если использовать термин kineti c (как есть обычно в классической механике) гарантированно будет иметь квадратичные c скорости. Затем, непосредственно извлекая матрицу этой квадратичной c формы, можно было бы делегировать системное решение в преобразовании импульсов в скорость числовому линейному решателю системы, поэтому не сохраняйте выражения symboli c для обращения матрицы. Они могут быть большими в более высоких размерах.

...