常微分方程式¶

In [1]:
import numpy as np
from scipy.integrate import solve_ivp
# from scipy.integrate import odeint
import matplotlib.pyplot as plt
import pandas as pd
In [2]:
# x0, y0: 初期条件,y0 = y'(x0)
# xs: yを求めるxの値
# dfunc: 導関数
# n: 区間数
# y: 数値解,y = y(xs)
def euler(dfunc, x0, y0, xs, n): # オイラー法(Euler method)
    h = (xs-x0)/n
    y = y0
    for i in range(n):
        x = x0+h*i
        y = y+h*dfunc(x,y)
    return y
In [3]:
# x0, y0: 初期条件,y0 = y'(x0)
# xs: yを求めるxの値
# dfunc: 導関数
# n: 区間数
# y: 数値解,y = y(xs)
def rk4(dfunc, x0, y0, xs, n): # 4次のルンゲ・クッタ法
    h = (xs-x0)/n
    h2 = h*0.5
    y = y0
    for i in range(n):
       x = x0+h*i
       k1 = h*dfunc(x,y)
       k2 = h*dfunc(x+h2,y+k1*0.5)
       k3 = h*dfunc(x+h2,y+k2*0.5)
       k4 = h*dfunc(x+h,y+k3)
       y = y+(k1+2.0*(k2+k3)+k4)/6.0
    return y
In [4]:
def dfunc7(x,y):# 微分方程式 y' = dy/dx = f(x,y)
    dydx = -4.0*(x-1.0)*y
    return dydx
In [5]:
def func7(x):# 微分方程式を解析的に解いて得られた関数
    y = np.exp(-2.0*(x-1.0)*(x-1.0))
    return y
In [6]:
eps = 1.0e-9
n, m = 500, 31
x00, y00 = 0.0, np.exp(-2.0)# 初期条件 for func7
xe = 3.0
dx = (xe-x00)/(m-1)
x0 = x00
y0a, y0b, y0c = y00, y00, y00
y_ini = np.array([y00])
print(f"{'x':>8s} {'solve_ivp':>10s} {'er':>13s} {'Euler':>10s} "\
      f"{'er2':>13s} {'rk4':>10s} {'er4':>13s}")
df = pd.DataFrame({'$x$':[],'solve_ivp':[],'er':[],'Euler':[],'er2':[],'rk4':[],'er4':[],})
for i in range(m):
    x = x00+dx*i
    y = func7(x)
    y1 = euler(dfunc7, x0, y0a, x, n)
    y4 = rk4(dfunc7, x0, y0c, x, n)
    solver = solve_ivp(dfunc7, [x0, x], y_ini, dense_output=True, method='DOP853')
    y5 = solver.sol(x)
    print(f"{x:8.3f} {y5[0]:10.6f} {y5[0]-y:13.10f} {y1:10.6f} "\
          f"{y1-y:13.10f} {y4:10.6f} {y4-y:13.10f}")
    x0 = x
    y0a, y0c = y1, y4
    y_ini = y5.copy()
    df1 = pd.DataFrame({'$x$':[x,],'solve_ivp':[y5[0],],'er':[y5[0]-y,],
                                      'Euler':[y1,],'er2':[y1-y,],
                                      'rk4':[y4,],'er4':[y4-y,]},index=[i,])
    df = pd.concat([df, df1])
       x  solve_ivp            er      Euler           er2        rk4           er4
   0.000   0.135335  0.0000000000   0.135335  0.0000000000   0.135335  0.0000000000
   0.100   0.197899  0.0000000000   0.197878 -0.0000206774   0.197899 -0.0000000000
   0.200   0.278037  0.0000000000   0.277987 -0.0000500973   0.278037 -0.0000000000
   0.300   0.375311  0.0000000000   0.375225 -0.0000864315   0.375311 -0.0000000000
   0.400   0.486752  0.0000000000   0.486627 -0.0001255903   0.486752  0.0000000000
   0.500   0.606531  0.0000000000   0.606369 -0.0001616715   0.606531  0.0000000000
   0.600   0.726149  0.0000000000   0.725961 -0.0001881401   0.726149  0.0000000000
   0.700   0.835270  0.0000000000   0.835071 -0.0001994950   0.835270  0.0000000000
   0.800   0.923116  0.0000000000   0.922923 -0.0001929179   0.923116  0.0000000000
   0.900   0.980199  0.0000000000   0.980029 -0.0001693099   0.980199  0.0000000000
   1.000   1.000000  0.0000000000   0.999867 -0.0001332711   1.000000  0.0000000000
   1.100   0.980199  0.0000000000   0.980107 -0.0000919499   0.980199  0.0000000000
   1.200   0.923116  0.0000000000   0.923063 -0.0000531152   0.923116  0.0000000000
   1.300   0.835270  0.0000000000   0.835247 -0.0000231094   0.835270  0.0000000000
   1.400   0.726149  0.0000000000   0.726144 -0.0000053686   0.726149  0.0000000000
   1.500   0.606531  0.0000000000   0.606531  0.0000000485   0.606531  0.0000000000
   1.600   0.486752  0.0000000000   0.486748 -0.0000041131   0.486752  0.0000000000
   1.700   0.375311  0.0000000000   0.375298 -0.0000135808   0.375311 -0.0000000000
   1.800   0.278037  0.0000000000   0.278013 -0.0000240024   0.278037 -0.0000000000
   1.900   0.197899  0.0000000000   0.197867 -0.0000320749   0.197899 -0.0000000000
   2.000   0.135335  0.0000000000   0.135299 -0.0000360846   0.135335 -0.0000000000
   2.100   0.088922 -0.0000000000   0.088886 -0.0000358518   0.088922  0.0000000000
   2.200   0.056135 -0.0000000000   0.056102 -0.0000322734   0.056135  0.0000000000
   2.300   0.034047 -0.0000000000   0.034021 -0.0000267288   0.034047  0.0000000000
   2.400   0.019841 -0.0000000000   0.019821 -0.0000205696   0.019841  0.0000000000
   2.500   0.011109 -0.0000000000   0.011094 -0.0000148095   0.011109  0.0000000000
   2.600   0.005976  0.0000000000   0.005966 -0.0000100241   0.005976  0.0000000000
   2.700   0.003089  0.0000000000   0.003082 -0.0000064020   0.003089  0.0000000000
   2.800   0.001534  0.0000000000   0.001530 -0.0000038686   0.001534  0.0000000000
   2.900   0.000732  0.0000000000   0.000730 -0.0000022166   0.000732  0.0000000000
   3.000   0.000335  0.0000000000   0.000334 -0.0000012064   0.000335  0.0000000000
In [7]:
df.style.format({"$x$":"{:.1f}", "er1":"{:.11f}", "er2":"{:.11f}", "er4":"{:.11f}"})
Out[7]:
  $x$ solve_ivp er Euler er2 rk4 er4
0 0.0 0.135335 0.000000 0.135335 0.00000000000 0.135335 0.00000000000
1 0.1 0.197899 0.000000 0.197878 -0.00002067743 0.197899 -0.00000000000
2 0.2 0.278037 0.000000 0.277987 -0.00005009735 0.278037 -0.00000000000
3 0.3 0.375311 0.000000 0.375225 -0.00008643152 0.375311 -0.00000000000
4 0.4 0.486752 0.000000 0.486627 -0.00012559025 0.486752 0.00000000000
5 0.5 0.606531 0.000000 0.606369 -0.00016167145 0.606531 0.00000000000
6 0.6 0.726149 0.000000 0.725961 -0.00018814012 0.726149 0.00000000000
7 0.7 0.835270 0.000000 0.835071 -0.00019949496 0.835270 0.00000000000
8 0.8 0.923116 0.000000 0.922923 -0.00019291789 0.923116 0.00000000000
9 0.9 0.980199 0.000000 0.980029 -0.00016930991 0.980199 0.00000000000
10 1.0 1.000000 0.000000 0.999867 -0.00013327115 1.000000 0.00000000000
11 1.1 0.980199 0.000000 0.980107 -0.00009194987 0.980199 0.00000000000
12 1.2 0.923116 0.000000 0.923063 -0.00005311517 0.923116 0.00000000000
13 1.3 0.835270 0.000000 0.835247 -0.00002310940 0.835270 0.00000000000
14 1.4 0.726149 0.000000 0.726144 -0.00000536856 0.726149 0.00000000000
15 1.5 0.606531 0.000000 0.606531 0.00000004851 0.606531 0.00000000000
16 1.6 0.486752 0.000000 0.486748 -0.00000411307 0.486752 0.00000000000
17 1.7 0.375311 0.000000 0.375298 -0.00001358083 0.375311 -0.00000000000
18 1.8 0.278037 0.000000 0.278013 -0.00002400239 0.278037 -0.00000000000
19 1.9 0.197899 0.000000 0.197867 -0.00003207488 0.197899 -0.00000000000
20 2.0 0.135335 0.000000 0.135299 -0.00003608460 0.135335 -0.00000000000
21 2.1 0.088922 -0.000000 0.088886 -0.00003585179 0.088922 0.00000000000
22 2.2 0.056135 -0.000000 0.056102 -0.00003227338 0.056135 0.00000000000
23 2.3 0.034047 -0.000000 0.034021 -0.00002672876 0.034047 0.00000000000
24 2.4 0.019841 -0.000000 0.019821 -0.00002056956 0.019841 0.00000000000
25 2.5 0.011109 -0.000000 0.011094 -0.00001480953 0.011109 0.00000000000
26 2.6 0.005976 0.000000 0.005966 -0.00001002415 0.005976 0.00000000000
27 2.7 0.003089 0.000000 0.003082 -0.00000640203 0.003089 0.00000000000
28 2.8 0.001534 0.000000 0.001530 -0.00000386860 0.001534 0.00000000000
29 2.9 0.000732 0.000000 0.000730 -0.00000221665 0.000732 0.00000000000
30 3.0 0.000335 0.000000 0.000334 -0.00000120640 0.000335 0.00000000000
In [8]:
#solve_ivp?
In [9]:
plt.figure()
plt.plot(df["$x$"], df["solve_ivp"], label='solve_ivp (DOP853)')
plt.plot(df["$x$"], df["Euler"], 'o--', label='Euler')
plt.plot(df["$x$"], df["rk4"], 's--', label='RK4')
plt.xlabel("x")
plt.ylabel("y")
plt.title("Euler, RK4, solve_ivp")
plt.legend()
plt.grid()
plt.show()
No description has been provided for this image