SciPy の integrate.odeint 関数を使用して、硬い ODE のシステムを統合しています。統合は簡単ではなく、時間がかかるため、対応する jacobian も使用しています。方程式を並べ替えることで、ヤコビアンを帯行列として定義できます。API ドキュメントに従って、muおよびmlパラメータで形状を定義したいと思います。残念ながら、ドキュメントは少しあいまいであるため、jacobian 関数を実装する方法を理解できませんでした。
odeintを呼び出す方法を確認するために、次の (ややばかげた) コードを使用しています。
from scipy.integrate import odeint
lmax = 5
def f1(y, t):
ydot = np.zeros(lmax)
for i in range(lmax):
ydot[i] = y[i]**2-y[i]**3
return ydot
def fulljac(y, t,):
J = np.zeros((lmax, lmax))
J[0,0]=-3*y[0]**2 + 2*y[0]
J[1,1]=-3*y[1]**2 + 2*y[1]
J[2,2]=-3*y[2]**2 + 2*y[2]
J[3,3]=-3*y[3]**2 + 2*y[3]
J[4,4]=-3*y[4]**2 + 2*y[4]
return J
## initial conditions and output times
delta = 0.0001;
yini = np.array([delta]*lmax)
times = np.linspace(0, 2/delta, 100)
y, infodict = odeint(f1, yini, times, Dfun=fulljac, full_output=1)
print("f1: nst: {0}, nfe: {1}, nje: {2}".format(infodict["nst"][-1],
infodict["nfe"][-1],
infodict["nje"][-1]))
完全な NxN ヤコビ行列を使用すると、統合は成功します。対角線のみを使用し、mu=0およびml=0を使用すると、積分も成功します。
バンド行列のユース ケースをテストするために、 mu=1とml= 1を使用して人工的な 3xN バンド ヤコビアンを作成しています。ここで、対角線からの導関数はすべてゼロです。これにより、ソルバーの奇妙な動作が発生します (非対角がゼロでない元の問題で見られるものと同様です)。
def bandjac(y, t):
J = np.zeros((lmax, 3))
J[0,1]=-3*y[0]**2 + 2*y[0]
J[1,1]=-3*y[1]**2 + 2*y[1]
J[2,1]=-3*y[2]**2 + 2*y[2]
J[3,1]=-3*y[3]**2 + 2*y[3]
J[4,1]=-3*y[4]**2 + 2*y[4]
return J
y, infodict = odeint(f1, yini, times, Dfun=bandjac, full_output=1, mu=1, ml=1)
print("f1: nst: {0}, nfe: {1}, nje: {2}".format(infodict["nst"][-1],
infodict["nfe"][-1],
infodict["nje"][-1]))
SciPyのintegrate.odeintでbanded jacobianオプションを使用する適切な方法は何ですか?