I have been working on a problem that involves solving 2 pairs of coupled ode's. It has been recommended that we use scipy solve_ivp to do this however it seems to be either freezing or running extremely slowly (I have ran this for up to half an hour with no results).
I have limited experience with solving ode's numerically and have never used solve_ivp before so this could be a simple error but I have been unable to find it.
import numpy as np
from matplotlib import pyplot as plt
from scipy import integrate as sc
param_dict = {
'r1': 0.36,
'r2': 0.15,
'k1': 4000000,
'b12': 0.0000002,
'b21': 0.69,
'p1': 80,
'p2': 275,
'q1': 0.0002,
'q2': 0.0004,
'phi1': 0.00095,
'phi2': 0.000075,
'c1': 20000,
'c2': 30000
}
# INITIAL VALUES
init_X = np.array([4000000,275000])
init_E = np.array([800,200])
y0 = np.concatenate((init_X, init_E))
def functions(t, X, r1, r2, k1, b12, b21, q1, q2, phi1, phi2, c1, c2, p1, p2):
x1, x2, y1, y2 = X
dx1dt = (r1 * x1) * (1 - (x1 / k1) - (b12 * x2)) - (q1 * y1 * x1)
dx2dt = (r2 * x2) * (1 - (x2 / (b21 * x1))) - (q2 * y2 * x2)
dy1dt = phi1 * y1 * (p1*q1 * x1 - c1)
dy2dt = phi2 * y2 * (p2*q2 * x2 - c2)
return [dx1dt, dx2dt, dy1dt, dy2dt]
t_span = [0,20]
t = np.linspace(0,100,1000)
res = sc.solve_ivp(functions, t_span, y0, args=tuple(param_dict.values()), dense_output=True)
zz = res.sol(t)
x1 = []
x2 = []
e1 = []
e2 = []
for ii in range(len(zz.T)):
x1.append(zz.T[ii,0])
x2.append(zz.T[ii,1])
e1.append(zz.T[ii,2])
e2.append(zz.T[ii,3])
plt.plot(x1)
plt.plot(x2)
If I set init_E = [0,0]
it runs seemingly as expected however any other value here seems to lead to this freezing/extremely slow problem.
The model here describes a predator/prey model for fisheries management for those interested.
I think the problem might be that the keys in your dictionary are not in the same order as the arguments to your function.
If I do the following it solves immediately.
param_names = ['r1', 'r2', 'k1', 'b12', 'b21', 'q1', 'q2', 'phi1',
'phi2', 'c1', 'c2', 'p1', 'p2']
args = tuple(param_dict[p] for p in param_names)
res = sc.solve_ivp(functions, t_span, y0, args=args, dense_output=True)
(Not sure if this is the correct solution but it doesn't hang up).
Bit of advice:
f0 = functions(0, y0, *args)
assert np.array_equal(f0, [-719200.0, 15139.945652173912, 33440.0, 3.75])