常微分方程式
|
SciPy常微分方程式SciPy モジュールを使った常微分方程式の数値計算の方法を示します. 目次はじめにodeint とはPython の scipy パッケージの odeint モジュールを使うと,とても簡単に微分方程式の数値解を得ることができます.このパッケージが計算することができる方程式は,1階の常微分方程式です.1階であれば,連立微分方程式の計算も可能です.したがって,高階の常微分方程式の計算も可能と言うことです.どんな高階の微分方程式でも,1階の連立微分方程式に変換できるからです.これについては,「高階の常微分方程式」を参照願います. odeint のアルゴリズムは, 使い方1階の常微分方程式の数値解を得るためには,(1)常微分方程式と(2)初期条件が必要です. とりあえず使ってみようまず簡単な微分方程式を odeint を使い,数値計算します.例として, \begin{align} \ddiffA{y}{x}=\cos(x) \end{align}の解を数値計算で求めます.初期条件は,\(y(0)=0\) とします. 001 # -*- coding: utf-8 -*- 002 003 import numpy as np 004 import matplotlib.pyplot as plt 005 from scipy.integrate import odeint 006 007 # =========================================================== 008 # 常微分方程式を解くクラス 009 # =========================================================== 010 class ODE(object): 011 012 # ------------------------------------------------------- 013 # コンストラクター 014 # ------------------------------------------------------- 015 def __init__(self, diff_eq, init_con): 016 017 self.diff_eq = diff_eq 018 self.init_con = init_con 019 020 021 # ------------------------------------------------------- 022 # 常微分方程式の計算 023 # ------------------------------------------------------- 024 def cal_euation(self, x_min, x_max, N): 025 026 x = np.linspace(x_min, x_max, N) # x の配列の生成 027 y = odeint(self.diff_eq, self.init_con, x) # 方程式の計算 028 029 return x, y 030 031 032 033 # ------------------------------------------------------- 034 # 解くべき常微分方程式 035 # ------------------------------------------------------- 036 def diff_eq(y, x): 037 dydx = np.cos(x) 038 return dydx 039 040 041 # ------------------------------------------------------- 042 # プロット 043 # ------------------------------------------------------- 044 def plot(x, y, x_range, y_range): 045 fig = plt.figure() 046 047 # ----- プロットの準備 ----- 048 sol = fig.add_subplot(1,1,1) 049 sol.set_xlabel("x", fontsize=20, fontname='serif') 050 sol.set_ylabel("y", fontsize=20, fontname='serif') 051 sol.tick_params(axis='both', length=10, which='major') 052 sol.tick_params(axis='both', length=5, which='minor') 053 sol.set_xlim(x_range) 054 sol.set_ylim(y_range) 055 sol.minorticks_on() 056 sol.plot(x, y, 'b-', markersize=5) 057 058 # ----- スクリーン表示 ----- 059 fig.tight_layout() 060 plt.show() 061 062 # ----- pdf 作成 ----- 063 fig.savefig('ode_solve.pdf', orientation='portrait', \ 064 transparent=False, bbox_inches=None, frameon=None) 065 fig.clf() 066 067 068 069 # ------------------------------------------------------- 070 # メイン関数 071 # ------------------------------------------------------- 072 if __name__ == "__main__": 073 074 N = 1000 # 分割数 075 min_x = 0 # x の最小 076 max_x = 4*np.pi # x の最大 077 initial_condition = np.array([0]) # 初期条件 078 079 ode = ODE(diff_eq, initial_condition) 080 x, y = ode.cal_euation(min_x, max_x, N) 081 082 plot(x, y, (min_x, max_x), (-1.2, 1.2)) 083 このプログラムの動作は,以下のとおりです.Matplotlib でプロットしているコマンドは,009 — 010 に書かれています.
プロット作成については,Matplotlib のページを参照ください. いろいろな常微分方程式連立微分方程式カオスの研究で有名な「ローレンツ方程式」を数値計算します.解くべき微分方程式は, \begin{align} &\ddiffA{x}{t}=-px+py& &\ddiffA{y}{t}=-xz+rx-y& &\ddiffA{z}{t}=xy-bz \end{align}です.これを変数は \((p,\,q,\,b)=(10,\,28,\,8/3)\) で,初期値 \((x,\,y,\,z)=(0.1,\,0.1\,0.1)\) で数値計算します.odeint を使った Python のプログラム例を以下に示します. 001 # -*- coding: utf-8 -*- 002 003 import numpy as np 004 import matplotlib.pyplot as plt 005 from mpl_toolkits.mplot3d import Axes3D 006 from scipy.integrate import odeint 007 008 # =========================================================== 009 # 常微分方程式を解くクラス 010 # =========================================================== 011 class ODE(object): 012 013 # ------------------------------------------------------- 014 # コンストラクター 015 # ------------------------------------------------------- 016 def __init__(self, diff_eq, init_con): 017 018 self.diff_eq = diff_eq 019 self.init_con = init_con 020 021 022 # ------------------------------------------------------- 023 # 常微分方程式の計算 024 # ------------------------------------------------------- 025 def cal_euation(self, t_min, t_max, N): 026 027 t = np.linspace(t_min, t_max, N) # x の配列の生成 028 v = odeint(self.diff_eq, self.init_con, t) # 方程式の計算 029 030 return v 031 032 033 034 # ------------------------------------------------------- 035 # 解くべき常微分方程式 036 # ------------------------------------------------------- 037 def diff_eq(v, t): 038 p = 10 039 r = 28 040 b = 8/3 041 dxdt = -p*v[0] + p*v[1] 042 dydt = -v[0]*v[2] + r*v[0] -v[1] 043 dzdt = v[0]*v[1] -b*v[2] 044 return [dxdt, dydt, dzdt] 045 046 047 # ------------------------------------------------------- 048 # プロット 049 # ------------------------------------------------------- 050 def plot(x, y, z): 051 fig = plt.figure() 052 053 # ----- プロットの準備 ----- 054 sol = fig.add_subplot(1,1,1, projection='3d') 055 sol.set_xlabel("x", fontsize=20, fontname='serif') 056 sol.set_ylabel("y", fontsize=20, fontname='serif') 057 sol.set_zlabel("z", fontsize=20, fontname='serif') 058 sol.tick_params(axis='both', length=10, which='major') 059 sol.tick_params(axis='both', length=5, which='minor') 060 sol.minorticks_on() 061 062 sol.plot(x, y, z, 'b-', markersize=0) 063 064 # ----- スクリーン表示 ----- 065 fig.tight_layout() 066 plt.show() 067 068 # ----- pdf 作成 ----- 069 fig.savefig('Lorenz.pdf', orientation='portrait', \ 070 transparent=False, bbox_inches=None, frameon=None) 071 fig.clf() 072 073 074 075 # ------------------------------------------------------- 076 # メイン関数 077 # ------------------------------------------------------- 078 if __name__ == "__main__": 079 080 N = 10001 # 分割数 081 min_t = 0 # t の最小 082 max_t = 100 # t の最大 083 initial_condition = np.array([0.1, 0.1, 0.1]) # 初期条件 084 085 ode = ODE(diff_eq, initial_condition) 086 v = ode.cal_euation(min_t, max_t, N) 087 088 plot(v[:, 0], v[:,1], v[:,2]) 089 高階の微分方程式これまで計算した常備分方程式はいずれも1階でしたが,ここでは2階の微分方程式を計算します.例として,調和振動子を表す微分方程式 \begin{align} \ddiffB{2}{x}{t}=-x \end{align}を計算します.この2階の微分方程式は, \begin{align} &\ddiffA{x}{t}=v& &\ddiffA{v}{t}=-x& \end{align}と書きなおすことができます.1階の連立微分方程式なので,odeint で計算することができます.初期条件 odeint の詳細クラス scipy.integrate.odeint の引数は,次のとおりです. scipy.integrate.odeint( func, y0, t, args=(), Dfun=None, col_deriv=0, full_output=0, ml=None, mu=None, rtol=None, atol=None, tcrit=None, h0=0.0, hmax=0.0, hmin=0.0, ixpr=0, mxstep=0, mxhnil=0, mxordn=12, mxords=5, printmessg=0)
ページ作成情報参考資料モジュール「pyplot.py」のソースコードが良い資料です. 更新履歴
|