フーリエ級数の収束(ディリクレ条件)

フーリエ級数は「あらゆる関数を三角関数の和で表せる」かのように思えますが、実際には収束するための条件があります。ディリクレ条件はフーリエ級数の収束を保証する十分条件です。

本記事の内容

  • ディリクレ条件
  • 各点収束と一様収束
  • 不連続点での収束値
  • ギブズ現象
  • Pythonでの可視化

前提知識

ディリクレ条件

周期関数 $f(t)$ が以下の条件を満たすとき、フーリエ級数は収束します:

  1. $f(t)$ は1周期内で区分的に連続
  2. $f(t)$ は1周期内で有限個の不連続点しか持たない
  3. $f(t)$ は1周期内で有限個の極値しか持たない(有界変動)

収束先

  • 連続点では $f(t)$ そのものに収束
  • 不連続点 $t_0$ では左極限と右極限の平均に収束:

$$ \frac{f(t_0^+) + f(t_0^-)}{2} $$

ギブズ現象

不連続点の近傍では、フーリエ級数の部分和にオーバーシュート(行き過ぎ)が生じます。これをギブズ現象と呼びます。

項数 $N$ を増やしてもオーバーシュートの割合は約 9% のまま残ります。ピークの位置は不連続点に近づきますが、振幅比は変わりません。

正確には、ジャンプ量 $d$ に対して最大オーバーシュートは約 $1.0895 \times d/2$ です。

Pythonでの可視化

import numpy as np
import matplotlib.pyplot as plt

T = 2*np.pi; omega = 2*np.pi/T
t = np.linspace(-np.pi, 3*np.pi, 2000)

def square_wave(t):
    return np.where(np.sin(t) >= 0, 1.0, -1.0)

fig, axes = plt.subplots(1, 3, figsize=(16, 5))

# (1) ギブズ現象:項数による変化
for N in [3, 9, 29, 99]:
    f_N = np.zeros_like(t)
    for n in range(1, N+1, 2):
        f_N += 4/(n*np.pi) * np.sin(n*t)
    axes[0].plot(t, f_N, lw=1.2, label=f'N={N}')
axes[0].plot(t, square_wave(t), 'k--', lw=1, alpha=0.4, label='Original')
axes[0].set_xlabel('$t$'); axes[0].set_ylabel('$f(t)$')
axes[0].set_title('Gibbs phenomenon', fontsize=13)
axes[0].legend(fontsize=9); axes[0].grid(True, alpha=0.3)
axes[0].set_xlim(-0.5, 2*np.pi+0.5)

# (2) 不連続点付近の拡大
t_zoom = np.linspace(-0.3, 0.3, 1000)
for N in [9, 29, 99, 299]:
    f_N = np.zeros_like(t_zoom)
    for n in range(1, N+1, 2):
        f_N += 4/(n*np.pi) * np.sin(n*t_zoom)
    axes[1].plot(t_zoom, f_N, lw=1.5, label=f'N={N}')
axes[1].axhline(1, color='k', ls='--', alpha=0.3)
axes[1].axhline(0, color='gray', ls='-', alpha=0.3)
axes[1].set_xlabel('$t$'); axes[1].set_ylabel('$f(t)$')
axes[1].set_title('Zoom near discontinuity', fontsize=13)
axes[1].legend(); axes[1].grid(True, alpha=0.3)

# (3) 最大オーバーシュート vs N
N_range = np.arange(3, 200, 2)
max_overshoot = []
for N in N_range:
    t_fine = np.linspace(0.001, 0.5, 5000)
    f_N = np.zeros_like(t_fine)
    for n in range(1, N+1, 2):
        f_N += 4/(n*np.pi) * np.sin(n*t_fine)
    max_overshoot.append(np.max(f_N))

axes[2].plot(N_range, max_overshoot, 'b-', lw=1.5)
axes[2].axhline(1.0, color='k', ls='--', alpha=0.3, label='Target = 1.0')
axes[2].axhline(1.0895*2/np.pi*2, color='r', ls=':', alpha=0.5, label='~1.089')
axes[2].set_xlabel('Number of terms $N$'); axes[2].set_ylabel('Max value near $t=0$')
axes[2].set_title('Gibbs overshoot convergence', fontsize=13)
axes[2].legend(); axes[2].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

まとめ

  • ディリクレ条件: 区分的連続、有限個の不連続点、有界変動
  • 連続点: フーリエ級数は $f(t)$ に収束
  • 不連続点: $(f(t^+) + f(t^-))/2$ に収束
  • ギブズ現象: 不連続点近傍で約9%のオーバーシュートが残る

次のステップとして、以下の記事も参考にしてください。