Маятник ODE с использованием odeint

#python #odeint

#python #odeint

Вопрос:

Я пытаюсь решить простую механическую проблему, которая является проблемой нелинейного простого маятника.

Для этого я должен использовать odeint из scipy.

Для напоминания я должен решить нелинейную ОДУ, которая: theta'' w²*sin(theta) = 0

Вот что у меня есть на данный момент, я должен определить функцию, которая возвращает положение маятника, то есть theta(t) :

 def ODE(omega,theta0,tf):
    """solution au bout tf avec odeint"""
    
    def F(Y,t,omega):
        """second membre de l'EDO"""
        return np.array([Y[1],-omega**2*np.sin(Y[0])])
    
    Y0 = np.array([theta0,0.])
    Y = odeint(F, Y0, tf, args=(omega,))
    return Y
 

Но когда я пытаюсь выполнить проверку с помощью этого, для сравнения с линейным решением:

 # test
theta0 = 0.1 
omega = 2.58
N = 15 
T = np.linspace(0,2*np.pi/omega,N)

    
# solution with odeint
ThetaODE = ODE(omega,theta0,T)


# linear solution
ThetaL = theta0*np.cos(omega*T)

# plot
plt.figure(figsize=(15,6))
plt.subplot(1,2,1)
plt.plot(T,ThetaODE,label="ODEint")
plt.plot(T,ThetaL,label="Lineaire")
plt.xlabel('t')
plt.legend()

plt.subplot(1,2,2)
plt.plot(T,ThetaL-ThetaODE)
plt.title('Ecart entre ODEint et la sol Lineaire')
plt.xlabel('t')
 

У меня такая ошибка:

 ValueError                                Traceback (most recent call last)
<ipython-input-128-d8b2832c3f6c> in <module>
     22 
     23 plt.subplot(1,2,2)
---> 24 plt.plot(T,ThetaL-ThetaODE)
     25 plt.title('Ecart entre ODEint et la sol Lineaire')
     26 plt.xlabel('t')

ValueError: operands could not be broadcast together with shapes (15,) (15,2) 
 

Должно быть что-то, что я неправильно понимаю в отношении odeint, есть идеи, что я делаю не так?
Спасибо!

Ответ №1:

Вы должны понимать, как работает библиотека odeint. Кстати, вместо этого вы должны использовать библиотеку solve_ivp : https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.solve_ivp.html#scipy.integrate.solve_ivp

В вашей системе есть две переменные: theta и ее производная по времени. Поэтому метод интеграции ODE odeint или solve_ivp вернет массив ( Y в вашей функции ODE ) с двумя измерениями. Одно измерение — это количество переменных (2), другое — количество временных точек, которые были вычислены между ними (чтобы контролировать это, обратитесь к документации).

Итак, здесь должна быть ваша сюжетная линия plt.plot(T,ThetaL-ThetaODE[:,0]) .

Совет здесь заключается в том, чтобы прочитать документы и поискать в Интернете похожие проблемы. Я думаю, вы бы легко нашли ответ. Существует множество руководств по интеграции ODE, поэтому, пожалуйста, найдите время, чтобы ознакомиться с некоторыми из них. Например, в этом есть несколько интересных примеров: https://scipy-cookbook.readthedocs.io/items/idx_ordinary_differential_equations.html

Здесь показано, как работать с pendulum: https://scientific-python.readthedocs.io/en/latest/notebooks_rst/3_Ordinary_Differential_Equations/04_Exercices/00_Tutorials/02_ODE_tutorial_pendulum.html

Вот графическая часть вашего кода с исправлениями:

 # plot the two solution components
plt.figure(figsize=(15,6))
plt.subplot(1,2,1)
plt.plot(T,ThetaODE[:,0],label=r"$theta$")
plt.plot(T,ThetaODE[:,1],label=r"$dot{theta}$")
plt.xlabel('t')
plt.grid()
plt.legend()

# compare the time evolution of the angle with the inear solution
plt.figure(figsize=(15,6))
plt.subplot(1,2,1)
plt.plot(T,ThetaODE[:,0] ,label="ODEint", linestyle='-', marker=' ')
plt.plot(T,ThetaL, label="Lineaire", linestyle='--', marker=None)
plt.xlabel('t')
plt.legend()

plt.subplot(1,2,2)
plt.plot(T,ThetaL-ThetaODE[:,0])
plt.title('Ecart entre ODEint et la sol Lineaire')
plt.xlabel('t')