第7回

1次元波動方程式の数値解法

(2021/03/03 最終修正)

ここでは,1次元波動方程式(wave equation)をコンピュータを用いて解くために差分化を行い,コンピュータを用いて波動方程式を解くアルゴリズムを示す.前回の拡散方程式に比べると、時間微分が2階になっているため、多少ややこしいが考え方は同じである。特に、初期条件の与え方がわかりにくいかも知れない。

さて,天下り的だが1次元波動方程式は弦の振動を(おおよそ)あらわす.次の動画は、1次元波動方程式をここで紹介する数値解法で解いた結果をアニメーションとしたものだ。 (こちらは、C言語+あるグラフィックライブラリで作成したアニメーション)

下記方程式 (W) における u(x,t) は弦の(静止位置からの)変位をあらわす.ここでは1次元波動方程式を数値計算を用いて解き,その解 u(x,t) をアニメーションとして表示する事を目標とする.つまり,コンピュータ内部に弦の振動を再現し,それをアニメーションとして表示するわけだ.

さて,次の1次元波動方程式の初期値境界値問題、

但し、c >0, f(0)=0, f(L)=0, g(0)=0, g(L)=0.

を考える。境界条件,初期条件が適切に与えられれば (W) の解が弦の振動を表現していると言えるだろう.さて,数値計算する為にまず(W)を離散化する必要がある。これはこれまでの常微分方程式の場合、また拡散方程式と共通で,要は微分を差分で置き換える必要がある.分割方法は以下の2種類が考えられるが,

ここでは時間方向の離散化は (1) を,空間方向の離散化は (2) を採用します.(前回の拡散方程式と同じ)

[0,l] 区間を N 等分するとし,上記離散化方法に従い,h = l/N, τ>0 とし,xj = (j - 1/2)h, tk = として,

と書くことにすると、(W)の第一式は次のように離散化される。

λ=/h として、まとめると

という式が得られる。2階微分の差分化については,このページ最後のスライドを参照.この式は、時刻 tk-1, tkでの U から次の時刻 tk+1での U が計算できるという形をしている。したがって、初期条件として、 Uj0,Uj1 が必要となる。まず Uj0は(W)の第三式より、

となる。 Uj1 を決める方法はいくつか考えられるが、例えば次のようにする。まず、テイラーの公式を用いると、

となる。(W)より

であり,さらに t=0 でも(W)の第一式が成り立つとすると、

となる。この式の右辺は2階差分商を用いて

と近似できる。つまり,

と求まる.

境界条件は(W)の第二式だが,まずは境界条件について触れる必要がある.ここでは,境界の処理の為に,U0k,UN+1k という架空のセルを用意することにする.

様々な境界条件があるが,今回の(W) における境界条件は Dirichlet 条件(この場合各時間 0 という値に固定されている.一般の場合,例えば a という値に固定されている場合には,次の式の右辺 0 が a となる.)と呼ばれるもの.空間離散化の方法として(1)を採用した事を思い出すと,

となればよいことが分かる.すなわち,

となる。(この辺り、拡散方程式と同じ)

まとめると、以下のようになる.

但し、 λ≦1 が安定性のための必要十分条件(安定性条件とは,数値計算がうまく行く為の条件).

めでたく差分方程式が得られた。(2)をコンピューターを用いて解くのがここでの目標である。状況を、次の絵を使って説明する。

縦軸方向を時間の進行方向とし,横軸方向を空間方向とする.赤色の円盤で示した位置の値 Ukj が,他の4点,Uk-1j ,Uk-1j-1 ,Uk-1j+1 ,Uk-2j ,から決定される様子.領域の端以外では上記のイメージで良いが,端においては境界条件の考慮が必要となる(前述).

1次元波動方程式を解く為のアルゴリズムは次のようになる。なお、安定性条件を満たすため、λをパラメータとして先に与えて、τは与えられたλから求めるようにする。

アルゴリズム中の uj, old_uj, new_uj はそれぞれ実数型の配列として定義すると良い.境界条件処理用に配列要素はN個よりも余分に2つ必要となり,計N+2個必要となる事に注意(new_uj については,実際には境界処理用の要素は用いない).例えば uj について,Python風に配列を定義すると,

u = [0.0]*(N+2)

となる.このようにすれば,u[0], u[1], ... , u[N+1] が用意される.実際そのように用意すれば良い.

以下のアルゴリズムのイメージ.new_u という配列要素を u および old_u という配列要素から求める.

初期条件における、new_u, u, old_u の関係は、old_u が時刻0の弦の形状、すなわち f(x)であり与えられているもの、u が時刻 τ における弦の形状であり、f(x)およびg(x)から決定されるもの、new_u はそれらから求まる時刻 2τ における弦の形状であり未知であるものとなっている。

アルゴリズム

(1)初期パラメータ設定

N, T, λ, c, l を設定する (λ ≦ 1)

h = l/N, τ=(λh)/c, M = T/τ

x, new_u, u, old_u を配列(リスト)として用意


(2) 初期値設定

j := 1,....,N の順に

x[j] = (j - 0.5)h

old_u[j] = f(x[j])

を繰り返す

old_u[0]=-old_u[1], old_u[N+1]=-old_u[N](境界条件:初期値決定のため)

j := 1,....,N の順に

u[j]=old_u[j]+τg(x[j])+(λ*λ)/2*(old_u[j-1]-2old_u[j]+old_u[j+1])

を繰り返す

(3)

k := 0,1,.....,M-1 の順に

(old_u[1] ~ old_u[N] を画面に表示)


u[0]=-u[1], u[N+1]=-u[N](境界条件)

j := 1,....,N の順に

new_u[j]=2u[j]-old_u[j]+(λ*λ)*(u[j-1]-2u[j]+u[j+1])

を繰り返す


j := 1,....,N の順に

old_u[j] = u[j]

を繰り返す


j := 1,....,N の順に

u[j] = new_u[j]

を繰り返す

を繰り返す


課題1(演習)

l=1, c=1, f(x)=2*x*(1-x), g(x)=0, u(0,t)=u(1,t)=0 として (2) を解くプログラムを作成せよ。(Nは100程度)

Code7-1.py : 1次元波動方程式のシミュレーション

# Code7-1.py

import math

import matplotlib.pyplot as plt

import matplotlib.animation as animation


T = 5.0

M = 5000

tau = T/float(M)

L = 1.0

N = 100

h = L/float(N)

C = 1.0

Lambda = C*tau/h

INTV = 100


print(Lambda)


def f(x):

return 2*x*(1.0 - x)

#return math.exp(-100*(x-0.4)*(x-0.4))


def g(x):

return 0.0

#return -200*(x - 0.4)*f(x)


x, old_u, u, new_u = [0.0]*(N+2), [0.0]*(N+2), [0.0]*(N+2), [0.0]*(N+2)


fig = plt.figure()

ims = []


for j in range(1, N+1):

x[j] = (j - 0.5)*h

old_u[j] = f(x[j])

old_u[0] = -old_u[1]

old_u[N+1] = -old_u[N]


for j in range(1, N+1):

u[j] = old_u[j] + tau*g(x[j]) + (Lambda*Lambda/2.0)*(old_u[j-1] - 2*old_u[j] + old_u[j+1])


for k in range(0, M+1):

t = k*tau

if k%INTV == 0:

im = plt.plot(x[1:N+1], u[1:N+1], linewidth=2, color="blue")

ims.append(im)


u[0] = -u[1]

u[N+1] = -u[N]

for j in range(1, N+1):

new_u[j] = 2*u[j] - old_u[j] + (Lambda*Lambda)*(u[j-1] - 2*u[j] + u[j+1])


for j in range(1, N+1):

old_u[j] = u[j]


for j in range(1, N+1):

u[j] = new_u[j]


plt.title("7-1")

plt.xlabel("x")

plt.ylabel("u(x,t)")

ani = animation.ArtistAnimation(fig, ims, interval=100, repeat=False)

plt.show()

#ani.save("anim.gif", writer="pillow", fps=10)

課題2

l=1, c=1, u(0,t)=u(1,t)=0 はそのままで、f(x) および g(x) を他のもにかえてみよ。(もっと局在化した初期値からはじめると、波の伝播が観察される。)

f(x)=exp(-100*(x-0.4)*(x-0.4))

とし、異なる g(x) を初期条件としたものを、

(a)waveeq2

(b)waveeq3

この時の g(x) は(a),(b)それぞれどのようなものか考えよ。

実際の弦の振動現象と照らし合わせ,f(x) および g(x) の意味を再考せよ.

課題3

弦の振動ではなく,膜の振動を考えたい.すなわち,1次元波動方程式ではなく2次元波動方程式を考える.どのような方程式になるであろうか?

2次元波動方程式を数値計算で解き、その結果を OpenGL という可視化ライブラリを用いて可視化したサンプルは以下の様。

これに近いものを、おまけ回に載せたので参考にして欲しい。

差分近似について.