12
Python で微分方程式の数値解法 水谷正大 2017 10 25 1 微分方程式の数値解法 x(t)=(x 1 (t),...,x n (t)) の初期条件 x(t 0 )=(x 1 (t 0 ),...,x n (t 0 )) のもとで空間 M 上の微分方程式系 dx 1 dt = v 1 (x,t), x 1 (t 0 )= x 10 . . . dx n dt = v n (x,t), x n (t 0 )= x n0 をベクトル表記して、次のように表す。 dx dt = v(x,t), x(t 0 )= x 0 この微分方程式は各点 x および時間 t 毎に接線ベクトル v R n を与えているとみることができ、 v : M R n ベクトル場 (vector filed) ということがある。 時間 t の経過による x の変化を dx dt = lim t0 x(t +∆t) - x(t) t と考えていることから、有限ではあるが十分小さい時間経過 t 後に対しては x(t +∆t) - x(t) t f (x,t) が期待できる。そこで微小であるが有限の時間刻み t ごとに、t をパラメータとする解曲線 x(t) 上に近い と考えられる離散的な値を逐次的に求める微分方程式の数値解法がさまざまに考案されてきた。 時刻 t = t 0 における初期条件 x(t 0 ) から逐次的に求めて得られる点列を {x n }(n =0, 1, 2,... ) と表記する x 0 = x(t 0 ))。以下では、簡単のために時間刻みを t を一定とする。 ここでは R 3 内の Lorentz 方程式 dx dt = -σx + σy dy dt = rx - y + xz dz dt = -bz + xy を取り上げよう。ここでは Lorenz による数値計算 (1963) にならってパラメータ σ = 10, r = 24.74, b =8/3 を固定しておく。 1.1 Euler 微分方程式の数値解法として、Euler とは、点列 x 0 , x 1 ,..., x n ,... を次のようにして逐次的に求める 方法である。 x n+1 = x n +∆tf (x n ,t n ), t n = t 0 + nt. 1

Python で微分方程式の数値解法 - 生田情報メディア …mizutani/python/print/diffeq/...次のPython 関数euler_orbit(x0, T, dt, f) は、Euler 法を使って解軌道の数値リストを求めている。vector

  • Upload
    lenga

  • View
    248

  • Download
    1

Embed Size (px)

Citation preview

  • Python

    2017 10 25

    1

    x(t) = (x1(t), . . . , xn(t)) x(t0) = (x1(t0), . . . , xn(t0)) M

    dx1dt

    = v1(x, t), x1(t0) = x10

    ...

    dxndt

    = vn(x, t), xn(t0) = xn0

    dx

    dt= v(x, t), x(t0) = x0

    x t v Rn v : M Rn

    (vector filed)

    t x

    dx

    dt= lim

    t0

    x(t+t) x(t)t

    t

    x(t+t) x(t)t

    f(x, t)

    t t x(t)

    t = t0 x(t0) {xn}(n = 0, 1, 2, . . . )x0 = x(t0) t

    R3 Lorentz

    dx

    dt= x+ y

    dy

    dt= rx y + xz

    dz

    dt= bz + xy

    Lorenz (1963) = 10, r = 24.74, b = 8/3

    1.1 Euler

    Euler x0,x1, . . . ,xn, . . .

    xn+1 = xn +tf(xn, tn), tn = t0 + nt.

    1

    http://journals.ametsoc.org/doi/pdf/10.1175/1520-0469(1963)020%3C0130%3ADNF%3E2.0.CO%3B2

  • Python euler_orbit(x0, T, dt, f) Euler

    vectorfield v m [v1, . . . , vm]

    t0 m2 width x0 = [x01, . . . , x0m]

    t0 t0 + T dt N = T/dt m [x0,x1, . . . ,xN ] 3 x0 x while

    orbit.append(list(x)) orbit

    1 def euler_orbit(x0, T, dt, vectorfield):

    2 width = len(x0)

    3 x = x0

    4 t = 0

    5 orbit = []

    6 orbit.append(list(x))

    7 while t > def func(x, y, *args):

    >> print a, b, args

    >> print func(a, b, c, d, e, f)

    (a, b, (c, d, e, f))

    >> print func(a, b, c, d)

    (a, b, (c, d))

    >> print func(a, b, c)

    2

  • (a, b, (c,))

    >> print func(a, b)

    (a, b, ())

    1.3 Euler Lorenz

    Lorenz (25), (26), (27) Euler diff_euler.py

    vector = [v1, v2, v3] Lorenz x0 = [0.1, 0.1, 0.1]

    1 0.01 Euler100 orbit

    diff euler.py

    1 #!/usr/bin/env python

    2 # -*- coding: utf-8 -*-

    3

    4 # vector fields v1, v2, v3 of Lorenz eq as functions of t, x, y, z.

    5 p, r, b = 10.0, 28.0, 8.0/3.0

    6 def v1(t, x, y, z):

    7 return(-p * x + p * y)

    8 def v2(t, x, y, z):

    9 return(-x * z + r * x - y)

    10 def v3(t, x, y, z):

    11 return(x * y - b * z)

    12

    13 def euler_orbit(x0, T, dt, vectorfield):

    14 width = len(x0)

    15 x = x0

    16 t = 0

    17 orbit = []

    18 while t

  • numpy matplotlibdiff euler.py

    1 # -*- coding: utf-8 -*-

    2 import numpy as np

    3 import matplotlib.pyplot as plt

    4 from mpl_toolkits.mplot3d.axes3d import Axes3D# for 3dim plot

    5 ....

    6 ....

    7 orbit = euler_orbit(x0, T, dt, vector)

    8

    9 xlist = []

    10 ylist = []

    11 zlist = []

    12 for x, y, z in orbit:

    13 xlist.append(x)

    14 ylist.append(y)

    15 zlist.append(z)

    16

    17 # plot in 3-din space

    18 fig = plt.figure()

    19 ax = fig.gca(projection=3d)

    20 ax.plot(xorbit, yorbit, zorbit)

    21 ax.set_xlabel(x(t))

    22 ax.set_ylabel(y(t))

    23 ax.set_zlabel(z(t))

    24 plt.show()

    1.2 diff_euler.py T= 50, dt = 0.01

    1.3.1 Numpy

    9-15 matplotlib

    Euler 3 x, y, z ( N

    N 3N 3 xorbit, yorbit zorbit N 3 NumPy NumPy ( import numpy as np

    np.ndarray(object)

    object np.ndarray

    np.array()

    Python Shell a 4 3Python a a[i][j]

    3 a[1][2] 2 35a[:]

    a[:][2] 2 3

    1 >>> import numpy as np

    2 >>> a = [[1,2,3], [4,5,6], [7,8,9], [10,11,12]]

    3 >>> a[1][2]

    4 6

    5 >>> a[:][2]

    6 [7, 8, 9]

    7 >>> na = np.array(a)

    8 >>> na[:, 2]

    9 array([ 3, 6, 9, 12])

    10 >>> na[1, :]

    4

  • 11 array([4, 5, 6])

    7 na = np.array(a) ndarray8 310 2

    arrayndarry A A[j,

    k]A[j][k]

    NumPy orbit 3 nporbit = np.array(orbit) N 3 ndarray xorbit, yorbit, zorbit16

    matplotlibdiff euler.py

    1 ....

    2 orbit = euler_orbit(x0, T, dt, vector)

    3 nporbit = np.array(orbit)

    4

    5 #xorbit = []

    6 #yorbit = []

    7 #zorbit = []

    8 #for x, y, z in orbit:

    9 # xorbit.append(x)

    10 # yorbit.append(y)

    11 # zorbit.append(z)

    12

    13 # plot in 3-din space

    14 fig = plt.figure()

    15 ax = fig.gca(projection=3d)

    16 ax.plot(nporbit[:, 0], nporbit[:, 1], nporbit[:, 2])

    17 .....

    1.3 EulerNumPy ndarray diff_euler.py

    T= 50, dt = 0.01

    1.4 Runge-Kutta

    Euler

    Runge-Kutta dt

    Python runge_kutta_orbit(x0, T, dt, vectorfield) Runge-Kutta

    vectorfield v m [v1, . . . , vm]

    t0 m 2 width x0 =

    [x01, . . . , x0m] t0 t0+T dtN = T/dt m [x0,x1, . . . ,xN ] 3 x0 x while

    orbit.append(list(x)) orbit

    Euler while tn = nt xn tn+1 = tn + dt

    xn+1 22,23 dt/2 k1, k2, k3, k4

    4

    1 def runge_kutta(x0, T, dt, vectorfield):

    2 width = len(x0)

    3 x = x0

    4 t = 0.0

    5 orbit = []

    6 while t

  • 10 k1 = list(map(lambda v: v(t, *x1), vectorfield))

    11 x2 = x

    12 for i in range(width):

    13 x2[i] += dt / 2.0 * k1[i]

    14 k2 = list(map(lambda v: v(t + dt / 2.0, *x2), vectorfield))

    15 x3 = x

    16 for i in range(width):

    17 x3[i] += dt / 2 * k2[i]

    18 k3 = list(map(lambda v: v(t + dt / 2.0, *x3), vectorfield))

    19 x4 = x

    20 for i in range(width):

    21 x4[i] += dt * k3[i]

    22 k4 = list(map(lambda v: v(t + dt, *x4), vectorfield))

    23 for i in range(width):

    24 x[i] += dt / 6.0 * (k1[i] + 2.0 * k2[i] + 2.0 * k3[i] + k4[i])

    25 t += dt

    26 return(orbit)

    1.4 diff_euler.pyRunge-Kutta Lorenz diff_runge.py

    T= 50, dt = 0.01 3

    LorenzEuler

    1 # lorenz system

    2 p, r, b = 10.0, 28.0, 8.0 / 3.0

    3 def v1(t, x, y, z):

    4 return(-p * x + p * y)

    5 def v2(t, x, y, z):

    6 return(-x * z + r * x - y)

    7 def v3(t, x, y, z):

    8 return(x * y - b * z)

    9 ....

    10 ....

    11 vector = [v1, v2, v3]

    12 x0 = [0.1, 0.1, 0.1]

    13 dt = 0.01

    14 T = 20

    15 orbit = runge_kutta(x0, T, dt, vector)

    2 Scipy

    Python Scipy Numpy Matplotlib

    Python matplotlib 3 1 Runge-

    Kett lorenz 3d.py dt = 0.005 T = 20

    5matplotlib.pyplot4mpl toolkits.mplot3d Axes3D

    Axes3D 74,75 ax75

    80(79) 3

    lorenz 3d.py1 #!/usr/bin/env python

    2 # -*- coding: utf-8 -*-

    3

    4 from mpl_toolkits.mplot3d import Axes3D

    5 import matplotlib.pyplot as plt

    6

    7 # vector fields f1, f2, f3 of Lorenz eq as functions of t, x, y, z.

    8 p, r, b = 10.0, 28.0, 8.0/3.0

    6

  • 1 lorenz 3d.py x0 = (0.1, 0.1, 0.1), dt = 0.005 T = 20.

    viewpoint

    9 def f1(t, x, y, z):

    10 return -p * x + p * y

    11 def f2(t, x, y, z):

    12 return -x * z + r * x - y

    13 def f3(t, x, y, z):

    14 return x * y - b * z

    15

    16 def euler(x0, T, dt, f):

    17 width = len(x0)

    18 x = x0

    19 t = 0

    20 orbit = []

    21 orbit.append(list(x))

    22 while t

  • 52 x[i] += dt/6 * (f1[i] + 2 * f2[i] + 2 * f3[i] + f4[i])

    53 t += dt

    54 return orbit

    55

    56

    57 func = [f1, f2, f3]

    58 x0 = [0.1, 0.1, 0.1]

    59 dt = 0.005

    60 T = 20

    61

    62 #### orbit = [[x0,y0,z0], [x1,y1,z1],[x2,y2,z2], ...]

    63 #orbit = euler(x0, T, dt, func)

    64 orbit = runge_kutta(x0, T, dt, func)

    65

    66 xorbit = []

    67 yorbit = []

    68 zorbit = []

    69 for i in range(len(orbit)):

    70 xorbit.append(orbit[i][0])

    71 yorbit.append(orbit[i][1])

    72 zorbit.append(orbit[i][2])

    73

    74 fig = plt.figure()

    75 ax = fig.gca(projection=3d)

    76 ax.set_xlabel(X)

    77 ax.set_ylabel(Y)

    78 ax.set_zlabel(Z)

    79 #ax.scatter(xorbit, yorbit, zorbit, zdir=y)

    80 ax.plot(xorbit, yorbit, zorbit, zdir=y)

    81 plt.show()

    3

    t t 0 span class=red/span

    t

    t f(x, t) t

    x(t+t) x(t) Coulomb

    strong/strong

    Runge-Kutta

    Lorenz

    Smale(1998)Mathematical Problems for the Next CenturyMathematical Intelligencer 20 (2): 7

    15 14

    W. Tucker(2002) A Rigorous ODE Solver and Smales 14th

    Problem

    4 Lorenz

    Edward N. Lorenz Deterministic Nonperiodic Flow J.

    8

    http://www6.cityu.edu.hk/ma/doc/people/smales/pap104.pdfhttp://www2.math.uu.se/~warwick/main/rodes.htmlhttp://www2.math.uu.se/~warwick/main/rodes.htmlhttp://www.math.sci.hokudai.ac.jp/~zin/papers/kokyuroku.pdfhttp://www.math.sci.hokudai.ac.jp/~zin/papers/kokyuroku.pdfhttp://journals.ametsoc.org/doi/pdf/10.1175/1520-0469%281963%29020%3C0130%3ADNF%3E2.0.CO%3B2

  • Atmos. Sci., 20(11963), 130 141)

    sensitive dependence

    on initial conditionschaos

    p = 10.0 , r = 28.04, b = 8.0/3

    p = 10, b = 8/3 r

    4.1 Poincare

    1 < r (0, 0, 0) 2 C

    C = (b(r 1),

    b(r 1), r 1)

    z 2 r 1 (x(t), y(t), z(t)) z = r 1 xy- z=r1 transverse z=r1 xy-/p p Lorenz 3

    x = (x, y, z) [x0, x1, . . . , xN ] z- [z0, z1, . . . , zN ]

    z z=r1

    [z0 (r 1), z1 (r 1), . . . , zN (r 1)]=[s0, s1, . . . , sN ], sj = zj (r 1)

    k xk z=r1 k + 1 zk+1

    zk (r 1) < 0 and zk+1 (r 1) < 0 sk > 0 and sksk+1 < 0

    z- xk z=r1

    z- xk (x, y) z=r1

    P Lorenz 2 C

    z=r1

    x x

    P :

    x P P (x) = x

    Poincaren

    n 1 Poincare lorenz section.py T = 100, dt = 0.05 Runge-Kutta Lorenz

    x, y, z- xorbit, yorbit, zorbit z- z=r1

    x, y- xsection, ysectionxy-

    2

    1 label=lorenz\_section.py]

    2 import matplotlib.pyplot as plt

    3 ...

    4 ...

    5 xorbit = []

    6 yorbit = []

    7 zorbit = []

    8 for i in range(len(orbit)):

    9 xorbit.append(orbit[i][0])

    10 yorbit.append(orbit[i][1])

    11 zorbit.append(orbit[i][2])

    9

  • 12

    13 xsection = []

    14 ysection = []

    15 for i in range(len(zorbit)-1):

    16 if zorbit[i]-(r-1) > 0 and zorbit[i+1] -(r-1) < 0:

    17 xsection.append(xorbit[i])

    18 ysection.append(yorbit[i])

    19

    20 plt.xlabel(x)

    21 plt.ylabel(y)

    22 plt.plot(xsection, ysection,rx)

    23 plt.show()

    2 Lorenz Poincare : T = 100 dt = 0.05 (0.1, 0.1, 0.1)

    SciPy z=r1

    2Lorenz Lorenz Lorenz

    Lorenz

    4.1 lorenz section.py z=r1

    Poincare

    4.2 Lorenz

    E. N. Lorenz Deterministic Nonperiodic Flow J. Atmos. Sci., 20(11963), 130 141)

    span class=bold blueLorenz/span

    z = r 1 2 C C+ C

    x(t) = (x1(t), x2(t), . . . , xn(t)

    xi- xi(t) tk tk t (tk, tk+) x(t) < x(tk) (ti)iN = t1, t2, . . . , tk, . . .xi(t) tk

    xk

    x1, x2, . . . , x

    k, . . .

    (x1, x2), (x

    2, x

    3), . . . , (x

    k1, x

    k), (x

    k, x

    k+1), . . . )

    Lorenz

    Lorenz3 x = (x, y, z) [x0, x1, . . . , xN ] z-

    10

    http://journals.ametsoc.org/doi/pdf/10.1175/1520-0469%281963%29020%3C0130%3ADNF%3E2.0.CO%3B2

  • z (z0, z1, . . . , zN ) dzi = zi+1 zi

    z1 z0, z2 z1, . . . , zi+1 zi, . . .

    zi1 < zi and zi > zi+1

    zi zmaxi Lorenz z-

    (zi) (0, 1] 2

    T (x) =

    {2x, x (0, 1/2)2 2x, x [1/2, 1)

    lorenz plot.py T = 100, dt = 0.05 Runge-Kutta Lorenz

    x, y, z- xorbit, yorbit, zorbit z zorbit Lorenz

    zorbit = [z0, z1, . . . , zN ] zdifi = zi+1 zi zi1 < zi and zi > zi+1 zi zextremum Lorenz

    transit = 2000

    lorenz plot.py

    1 # -*- coding: utf-8 -*-

    2 # numerila solution fo Lorenz system using scipy.integrate

    3 # Lorenz section

    4

    5 import numpy as np

    6 import matplotlib.pyplot as plt

    7 from scipy.integrate import odeint

    8

    9 # lorenz system

    10 p, r, b = 10.0, 28.0, 8.0 / 3.0

    11 def lorenz_system(x, t):

    12 vxt = -p * x[0] + p * x[1]

    13 vyt = -x[0] * x[2] + r * x[0] - x[1]

    14 vzt = x[0] * x[1] - b * x[2]

    15 return([vxt, vyt, vzt])

    16

    17 x0 = [0.1, 0.1, 0.1]# initial points

    18 t0 = 0

    19 T = 100

    20 dt = 0.01

    21

    22 # numerila solution using scipy.integrate

    23 times = np.arange(t0, T, dt)

    24 orbit = odeint(lorenz_system, x0, times)

    25 #print(orbit)

    26 # Poincare surface of section

    27 # z = r-1 x-y (x,y) plot28 xsectionlist = []

    29 ysectionlist = []

    30

    31 zhight = [0, 0, r-1]

    32 for k in range(len(orbit)-1):

    33 if (orbit[k] - zhight)[2] < 0 and (orbit[k] - zhight)[2] * (orbit[k+1] - zhight)[2] < 0:

    34 # if (orbit[k] - zhight)[2] * (orbit[k+1] - zhight)[2] < 0:

    35 xsectionlist.append(orbit[k,0])

    11

  • 36 ysectionlist.append(orbit[k,1])

    37

    38

    39 #plot using matplotlib

    40 ax = plt.axes()

    41 plt.xlabel(x)

    42 plt.ylabel(y)

    43 plt.plot(xsectionlist, ysectionlist, "x", markersize=1)

    44 plt.show()

    lorenz plot.py21-23 z-

    zextremum = [zmax,1, . . . , zmax,k1, zmax,k, zmax,k+1, . . . , zmax,Nk ] 26 29

    zpair = [. . . , (zmax,k1, zmax,k), (zmax,k, zmax,k+1), . . . ]

    2 {(zmax,k, zmax,i+k)}matplotlib x- y- zpairx, zpairy

    Lorenz 3

    3 Lorenz: T = 100, dt = 0.005, (x0, y0, z0) = (0.1, 0.1, 0.1)

    3 1 I I L

    L : I I

    z0 I zn+1 = Lzn = Lnz0 L z0, z1, z2, . . . Lorenz z

    Lorenz

    1 I L

    4.2 lorenz plot.pyLorenz

    12

    1 1.1 Euler1.2 1.3 EulerLorenz1.4 Runge-Kutta

    2 Scipy3 4 Lorenz4.1 Poincare4.2 Lorenz