Warm tip: This article is reproduced from stackoverflow.com, please click
differential-equations python runge-kutta scipy

Issue understanding scipy.integrate.RK45 requirements

发布于 2021-01-17 13:48:53

I am attempting to solve a system of first order differential equations with scipy.integrate.RK45(). I have scripted out the model function that I am hoping to plot (displacement vs time), but RK45() requires that this function takes 2 arguments, namely 't' and 'y', where 't' is a scalar and 'y' is an array in my case. This is better described below:

https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.RK45.html

My script is as follows:

import numpy as np
from scipy.integrate import RK45, RK23

# Model the calling function [X_dot]:
#------------------------------------------------------------------
def model(t, y):
    
    # Define the mass, stiffness and damping [m, c, k]:
    m = 2
    c = 10
    k = 1500

    # Define the piecewise forcing function [F]:
    if (t >= 0 and t < 0.1):
        F = 200 * t
    if (t >= 0.1 and t < 0.25):
        F = 20
    else:
        F = 0
    
    E_matrix = [[0, 1], [(-k / m), (-c / m)]]
    Q_matrix = [0, F / m]

    return E_matrix*X + Q_matrix

# Define the initial conditions and integration boundaries:
#------------------------------------------------------------------
time_step = 0.01
t_upper = 0.5
t_lower = 0

initial_conditions = [0, 0] # [displacement(t=0) = 0, velocity(t=0) = 0]

points_to_plot = RK45(fun=model(t, y), t0=t_lower, y0=initial_conditions, t_bound=t_upper, vectorized=True)

A picture of the system I'd like to solve is seen below: System of DEs

I have found very few examples of this being used as most solutions use odeint().

What are these two arguments (t, y) and how would I effectively incorporate them into my function? Any help is appreciated greatly.

Questioner
ChaddRobertson
Viewed
0
Pierre de Buyl 2020-09-18 20:49

You have used t already. Now, change def model(t, y): to def model(t, X): and you will use X as well. Note that t and y are positional arguments, you can call them however you like in your function. You have another issue, which is that you multiply Python lists! In Python, as opposed to Matlab, you need to specify that you make an array:

Change

E_matrix = [[0, 1], [(-k / m), (-c / m)]]
Q_matrix = [0, F / m]

to

E_matrix = np.array([[0, 1], [(-k / m), (-c / m)]])
Q_matrix = np.array([0, F / m])

and

return E_matrix*X + Q_matrix

to

return E_matrix @ X + Q_matrix

as @ is the matrix product in NumPy. * performs element-wise product.

EDIT: I hadn't spotted the call RK45(fun=model(t, y),. By doing that, you are passing the value of the function model at t,y. You need to give the function itself: RK45(fun=model, ...