Return to 真空中のマクスウェル方程式と電磁波

Matplotlib で1次元波動のグラフとアニメをつくる

ライブラリの import

In [1]:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator

from matplotlib.animation import FuncAnimation

# 以下はグラフを SVG で Notebook にインライン表示させる設定
%config InlineBackend.figure_formats = ['svg']

# mathtext font の設定
plt.rcParams['mathtext.fontset'] = 'cm'

1次元波動方程式の解

1次元波動方程式

$$\left( \frac{\partial^2}{\partial x^2} -\frac{1}{v^2} \frac{\partial^2 }{\partial t^2} \right) f = 0$$

の解は

$$f(x, t) = F(x -vt) + G(x + vt)$$

ここで,$F(x -vt)$ は $+x$ 方向に進む波,$G(x + vt)$ は $-x$ 方向に進む波を表す。

例として,$f(x, t) = \sin (x -vt)$ を $v=1$ としてグラフにしてみる。

In [2]:
def f(x, t):
    return np.sin(x - t)
In [3]:
# ax を使う際の最初のおまじない
fig, ax = plt.subplots()

# 横軸縦軸の ticks 
ax.set_xticks([])
ax.set_yticks([])

# 表示範囲
ax.axis([-10, 12,-1.2, 1.3 ])

# 矢印
ax.quiver([float(np.pi/2-2*np.pi), 
           float(np.pi/2), 
           float(np.pi/2+2*np.pi)], [1.1,1.1,1.1], [2,2,2], [0,0,0], 
          # 全ベクトルに色を一括指定
          color="black", 
          # 以下の3点セットを書かないと自動スケーリングされる
          angles='xy', scale_units='xy', scale=1)

# x軸 y軸は dashed に
ax.axhline(0, c='gray', ls='--', lw=0.5)
ax.axvline(0, c='gray', ls='--', lw=0.5)

# xの範囲
x = np.linspace(-10, 10, 200)

# t = 0
ax.plot(x, f(x, 0), label = '$t = 0.0$', 
        lw = 0.5, c = '#cccccc')
# t = 0.5
ax.plot(x, f(x, 0.5), label = '$t = 0.5$', 
        lw = 0.7, c = '#888888')
# t = 1.0
ax.plot(x, f(x, 1.0), label = '$t = 1.0$', 
        lw = 1, c = '#555555')
# t = 1.5
ax.plot(x, f(x, 1.5), label = '$t = 1.5$', 
        lw = 1.5, c = '#000000')

ax.set_title(r'$f(x, t) = \sin(x - v t)$')
ax.set_xlabel(r'$x \quad \rightarrow$')
ax.legend();

In [4]:
# ax を使う際の最初のおまじない
fig, ax = plt.subplots()

def func(i):
    # 前の frame を消す
    ax.cla()

    # 表示範囲
    ax.axis([-10, 10, -1.2, 1.2])
    # 横軸目盛
    ax.set_xticks([])
    # 縦軸目盛
    ax.set_yticks([])
    ax.set_title(r'$f(x, t) = \sin(x - v t)$')
    ax.set_xlabel(r'$x \quad \rightarrow$')
    ax.axhline(0, c='gray', ls='--', lw=0.5)
    ax.axvline(0, c='gray', ls='--', lw=0.5)

    t = 2*np.pi/frames * i
    # xの範囲
    x = np.linspace(-10, 10, 200)

    ax.plot(x, f(x, t), c = 'k')

# 変数名 frames は固定。
# 軌道全体を frames 個に分割してパラパラアニメに。
# frames 数を増やし,interval を短くすると滑らかに。
frames = 30
ani = FuncAnimation(fig, func,  
        # interval は frame 間の時間をミリ秒単位で。
        interval = 100, 
        # 端点も含めて frames 個のコマ数にしてみた。
        frames = range(frames))

# 動画を jupyterhub のホームに mp4 ファイルとして保存。
# 小綺麗な動画にするために解像度 dpi を設定
ani.save("wave-anim01.mp4", dpi=288)