Example 11-12: System of 2nd-order ODEs

Example 11-12: System of 2nd-order ODEs#

Now that we have worked with a system of 1st-order ODEs and 2nd-order ODEs (which are really just a system of 1st-order ODEs), it’s time to combine the two!

Summary of commands#

No new commands are demonstrated in this exercise, as it will be very similar to Example 11-10 and Example 11-11.

Moving body in a plane#

Consider the following system of second-order ODEs representing a body moving in a plane.

\[\begin{split} \begin{alignat}{2} x'' &= -9x + 4y + x' + e^t - 6t^2 &&= f_1(t, x, y, x', y') \\ y'' &= 2x - 2y + 3t^2 &&= f_2(t, x, y, x', y') \end{alignat} \end{split}\]

subject to the initial conditions:

\[ x(0) = 0; \quad x'(0) = 1; \quad y(0) = -1; \quad y'(0) = -20 \]

and the \(t\) range \(0 \le t \le 8\).

This is a rather complex system of 2nd-order ODEs. If we make the following substitutions (see course reader for details):

\[\begin{split} \begin{alignat}{2} x &= z_1 \quad &&\implies \quad z_1' &&= z_3 \\ y &= z_2 \quad &&\implies \quad z_2' &&= z_4 \\ x' &= z_3 \quad &&\implies \quad z_3' &&= -9z_1 + 4z_2 + z_3 + e^t - 6t^2 \\ y' &= z_4 \quad &&\implies \quad z_4' &&= 2z_1 - 2z_2 + 3t^2 \end{alignat} \end{split}\]

Then it is possible to solve the problem using the tools we’re already familiar with. At the end, we’ll plot the \(x\) and \(y\) positions as a function of time, as well as the \(xy\) trajectory.

# import libraries
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

# define custom function: z = [x, y, x', y']
def my_func(t, z):
    zp = np.zeros(4)
    zp[0] = z[2]
    zp[1] = z[3]
    zp[2] = -9 * z[0] + 4 * z[1] + z[2] + np.exp(t) - 6 * t ** 2
    zp[3] = 2 * z[0] - 2 * z[1] + 3 * t ** 2
    return zp

# constants
t0 = 0
tf = 8
x0 = 0
xp0 = 1
y0 = -1
yp0 = -20

# solve the ODE
solver = solve_ivp(my_func, [t0, tf], [x0, y0, xp0, yp0], max_step=0.01)
t, z = solver.t, solver.y

# plot the solution
fig, ax = plt.subplots(ncols=2, figsize=(10, 4.5))
ax[0].plot(t, z[0,:], lw=2.5, label='$x(t)$')
ax[0].plot(t, z[1,:], '--', lw=2.5, label='$y(t)$')
ax[0].set(xlabel="$t$", ylabel=r"$x(t)$, $y(t)$", title="Body position",
          xlim=[t0, tf], ylim=[-100, 500])
ax[0].legend()
ax[1].plot(z[0,:], z[1,:], lw=2.5)
ax[1].set(xlabel="$x(t)$", ylabel="$y(t)$", title="Body trajectory",
          xlim=[-100, 500], ylim=[-50, 400])
fig.tight_layout()
plt.show()
../_images/67a974910a7c4ccdefddec37777b716b696c3ce170bc49ee8f510ff380a2e0ea.png