Solving a system of 2nd order differential equations from sympy

。_饼干妹妹 提交于 2021-02-10 14:50:39

问题


I am doing a multiple DOF dynamics problem, using 2nd order Lagrangian equations. I used sympy to get to the equations of motion. Now these equations after calculating the derivatives got quite long, seems though that sympy simplify cant simplify it further. My problem actually is how to solve this system of three 2nd order ode from here. I don't know how to get these equations converted so they can be used with scipy.odeint(). Substitution came to mind, but there are a lot of symbols. So Im searching for phi0,phi1 and phi2 and also for their first and second derivatives. Initial conditions are all phi[0]=0 and all dphi[0]=0. I hope there is a way to solve this without going from scratch. Thanks in advance.

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

So my f0 is the one of the equations, I couldn't copy the output so I will post a picture.

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(𝑡)

And lambdify output:

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: So after a lof of simplification i some how got 3 ordinary differential equations. But they are in sympy form, how can i solve them numericaly?

−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:


I'll present the execution of the Euler-Lagrange formalism for the example of the double pendulum as a non-trivial, complete, standard example, and this without using the specialized functions in sympy.physics, only using basic differentiation and code-writing facilities of sympy. Hopefully it is general enough in that the second part should be problem-independent and thus also be directly applicable to your situation.

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

Lagrangian for the physical model

First the physical setup for the Lagrangian using the two angles as the main dependent functions and construct kinetic and potential energy via the Cartesian coordinates.

# 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()

To get an abstract treatment use abstract parameter arrays and coordinate vectors

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

From Euler-Lagrange to a first-order ODE system

It gets rather messy in the resulting expressions if one goes to the second derivatives of the angles, one gets a more structured approach and hopefully a correspondingly faster evaluation using impulse variables

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

where the first relation is seen as a system of equations to compute dotq from p.

Prepare the new variables, prepare to replace the function symbols with simple variables.

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)]

Now replace all function terms by simple variables

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

Now establish the function to compute dotq from 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])

Next generate a function that computes the derivatives of p

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

Now assemble the generated functions into a complete ODE function and solve a test problem with it to confirm that it works

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]

Confirmation via numerical solution

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()

This produces the following plot for the angle functions

Outlook

Even better performance could be expected if the kinetic term is (as is usual in classical mechanics) guaranteed to be quadratic in the velocities. Then by directly extracting the matrix of this quadratic form, one could delegate the system solution in the conversion of impuls to velocity to a numerical linear system solver, so not keep the symbolic expressions for the matrix inversion. These could be large in higher dimensions.



来源:https://stackoverflow.com/questions/61044226/solving-a-system-of-2nd-order-differential-equations-from-sympy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!