時間二階微分はどうする: Newton運動方程式
時間方向に二階微分がかかっている時間発展常微分方程式
これまでは
$$ \frac{du}{dt} = F(u,t) $$
というタイプの、時間方向の微分が一階しかない時間発展問題の常微分方程式を扱ってきた.
しかしもちろんのことながら、われわれが取り組みたい問題はこういうものばかりではなく、例えば
$$ \frac{d^2 u}{dt^2} = F(u,\frac{du}{dt}, t) $$
といったような、時間方向の微分が二階の問題や、三階、四階といった問題も考えうる.
こういう場合にどうしたらよいか、それを学んでみよう.
いわゆる Newton 運動方程式
時間方向に二階微分が入る時間発展問題の常微分方程式といえば、高校時代に学ぶ Newton の運動方程式がまずは挙げられよう. そこで、ここではそれを扱ってみよう.
具体的には、バネでぶら下げられている重りの挙動を例として考えてみよう. バネ定数を $k$, 重りの重さを $m$, 重力定数を $g$ とすれば、重りの高さ位置 $h(t)$ $(t: $時間$)$ についての Newton の運動方程式は
\begin{equation} m \frac{d^2 h}{dt^2} = -kh -mg \label{eq:newton-problem} \end{equation}
となる. むろん、解をきちんと考えるためにはさらに初期値等の情報が必要で、例えば
\begin{equation} \left\{ \begin{array}{ccl} h(0) & = & h_{ini}, \cr \displaystyle \frac{dh}{dt}(0) & = & v_{ini} \end{array} \right. \end{equation}
などという情報を付与しないといけない.
さて、これを例に、しばらく考察を進めてみよう.
(その前に) 保存量
計算について考える前に、この系の保存量を考えてみよう. これは高校の物理で学んだ通りで、全エネルギー = 運動エネルギー + 位置エネルギー が保存されるはずだ.
そして、運動エネルギーは
$$ \frac{1}{2} m \left( \frac{dh}{dt} \right)^2 $$
と表され、位置エネルギー = 力の積分 on 逆らって移動した距離 は
$$ \int_0^h (kx + mg) dx = \frac{1}{2} kh^2 + mgh $$
となることは覚えているだろうか? まあ思い出してもらうとして、全エネルギーは
\begin{equation} E(h(t)) = \frac{1}{2} m \left( \frac{dh}{dt} \right)^2 + \frac{1}{2} kh^2 + mgh \label{eq:energy-h} \end{equation}
となるわけなので、これがこの系の保存量である…はずだな.
高階微分が含まれる時間発展問題へのアプローチ 1a
高階微分が含まれる時間発展問題へのアプローチはいくつか考えられるが、いちばんストレートなのは「方程式はそのままに、そのまま離散近似する」という手法だろう.
例えば、問題 ($\ref{eq:newton-problem}$) に対して 近似解を $h_n \cong h(n\Delta t)$, $n = 0,1,2, \cdots$ として
$$ m \left( \frac{h_{n+1} - 2h_n + h_{n-1} }{\Delta t^2} \right) = -k h_n + mg $$
という近似式を提案する、などだ. もちろん初期値等の付与情報の離散化も必要で、この場合の安直な離散化は例えば次のようになるだろう.
\begin{equation} \left\{ \begin{array}{ccl} h_0 & = & h_{ini}, \cr \displaystyle \frac{h_1 - h_0}{\Delta t} & = & v_{ini} \end{array} \right. \end{equation}
tips: これはあくまで「例」であって、良いものかどうかは全く考慮していないことに注意しよう.実際は、たぶん、相当「悪い」離散化になっているだろう.
高階微分が含まれる時間発展問題へのアプローチ 1b
アプローチ 1a の改善版として考えられるアプローチは、「方程式はそのままに、離散化は工夫して」という手法だろう. これは悪くないアプローチだが、説明が少し必要だ.そこで詳しくは次回以降にするとしよう.
高階微分が含まれる時間発展問題へのアプローチ 2a
次に考えられるアプローチは、「従属変数を新たに必要なだけ導入して方程式を一階常微分方程式に変形し、その常微分方程式に対する汎用解法を適用する」という手法で王道といえるものだ.
話は簡単で、従属変数を新たに一つ導入すると全体の微分階数が 1階下げられるので(方程式は連立になる), これを必要なだけ繰り返せば良い. どういうことか、上の例で示してみよう.
まず、従属変数として、
$$ v(t) := \frac{dh}{dt} $$
を新たに導入する.すると元の方程式そのものは
\begin{equation} m\frac{d v}{dt} = -kh -mg \end{equation}
と書き換えることができて微分階数を一つ下げられる. よって全体としては(連立ではあるが)一階常微分方程式である次の形
\begin{equation} \left\{ \begin{array}{rcl} \displaystyle \frac{d h}{dt} & = & v, \cr \displaystyle m \frac{d v}{dt} & = & -kh -mg \end{array} \right. \label{eq:newton-system} \end{equation}
に帰着させられる、というわけだ.
あとはこの問題に対して、Euler 法でも時間対称離散化でも Runge-Kutta 法でもなんでも好きな汎用解法を適用すれば良い、というわけだ.
tips: この場合の全エネルギーは $$ E(h,v) = \frac{1}{2} m v^2 + \frac{1}{2} kh^2 + mgh $$ と表現される.
実際にやってみよう: Euler 法
Euler 法だと、近似値を $h_n \cong h(n\Delta t)$, $v_n \cong v(n\Delta t)$ として, まあ普通は近似式は次のようになるかな.
\begin{equation} \left\{ \begin{array}{rcl} \displaystyle \frac{h_{n+1} - h_n}{\Delta t} & = & v_n, \cr \displaystyle m \left( \frac{v_{n+1} - v_n}{\Delta t} \right) & = & -k h_n -mg . \end{array} \right. \end{equation}
書き換えると次のような感じだ.
\begin{equation} \left\{ \begin{array}{rcl} h_{n+1} & = & h_n + \Delta t \, v_n, \cr v_{n+1} & = & \displaystyle v_n + \Delta t \, (- \frac{k}{m} h_n -g), \end{array} \right. \end{equation}
あとはプログラミングだ.
定数等をまず定義して…
|
|
Euler 法の 1step を関数としていつものように定義しよう.
|
|
euler (generic function with 1 method)
エネルギーの計算式も定義しておいて、
|
|
energy (generic function with 2 methods)
早速動かしてみようではないか!
|
|
近似解をプロットしてみよう. まず準備.
|
|
Plots.GRBackend()
時間軸方向もデータを丁寧に用意して、
|
|
1-element Array{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},1}: 0.0:0.1:50.0
早速プロットしよう.
|
|
う~ん、バネにぶら下がった重りがびよんびよんしてるだけのはずなのに、振幅が大きくなっているってのはおかしいな…
エネルギーが保存されているか、プロットしてみよう.
|
|
う~ん、エネルギーがすごい勢いで「増えている」.こりゃだめだ.
念のために相図も描いておこう.
|
|
本来は保存系であることが明白なのに、数値解は一周してもとに戻ってこない.やはりまずいねえ…
Runge-Kutta 法なら?
というわけで、アプローチ 2a の「汎用解法」の部分を Runge-Kutta 法に切り替えてみよう. つまり、微分方程式 ($\ref{eq:newton-system}$) を、左辺 = 一階微分 の形式に書き直した
\begin{equation} \left\{ \begin{array}{rcl} \displaystyle \frac{d h}{dt} & = & v, \cr \displaystyle \frac{d v}{dt} & = & \displaystyle -\frac{k}{m} h -g \end{array} \right. \end{equation}
に対して Runge-Kutta 法を適用するわけだ.
あとはいつもどおりなので、さくさくやってみよう.
まず、微分方程式の右辺を定義する.
|
|
r (generic function with 1 method)
そしてそれを元に Runge-Kutta 法を適用したものを作ってしまう.
|
|
RK (generic function with 1 method)
エネルギー計算式も呼び出しやすい形式にしておこう.
|
|
energy (generic function with 2 methods)
あとは実際に計算するだけだ.
|
|
プロットしやすいように結果を切り出して…
|
|
プロットする.
|
|
おお、振動が一定になったぞ!
エネルギーもプロットしよう.
|
|
おお、だいぶ一定っぽくなってきた.
初期値を引いてプロットして、ズレを明らかにしよう.
|
|
計算の全過程を通じて、エネルギーがおおよそ 3桁程度の精度で保たれていることがわかる. ん~、まあ悪くない.良くもないがな.
相図も描いてみよう.
|
|
ふむ、図の上では一周して戻ってきた、と言ってよさそうだ.
高階微分が含まれる時間発展問題へのアプローチ 2b
次に考えられるアプローチは、「従属変数を新たに必要なだけ導入して方程式を一階常微分方程式に変形し、その常微分方程式に対する特別な解法を設計、適用する」という手法で、これもまあ王道といえよう.
この場合の 特別 というのはもちろん文脈依存なので、以下に「エネルギー保存性を再現するという意味で特別な」例を示そう.
まずは、先に示したように、 $v = dh/dt$ という従属変数を一つ新たに導入したときの全エネルギーは
$$ E(h,v) = \frac{1}{2} m v^2 + \frac{1}{2} k h^2 + mgh $$
となるはずだ. そして、ある時点 $t = n\Delta t$ での数値解 $h_n, v_n$ に対してエネルギーの数値近似値をやはりそっくりな式
\begin{equation} E_d(h_n, v_n) = \frac{1}{2} m v_n^2 + \frac{1}{2} k h_n^2 + mg h_n \label{eq:energy-hv} \end{equation}
であると定義しよう.
天下りであるが、例えば、次のような数値計算式で近似値 $h_{n+1}, v_{n+1}$ を計算すると、$E_d$ は変化しない(Why? は課題へ). つまり、$E_d(h_{n+1}, v_{n+1}) = E_d(h_n, v_n)$ となる.
\begin{equation}
\left\{\begin{array}{rcl}
\displaystyle \frac{h_{n+1} - h_n}{\Delta t} & = & \displaystyle \frac{v_{n+1} + v_n}{2} \cr
\displaystyle \frac{v_{n+1} - v_n}{\Delta t} & = & \displaystyle -\frac{k}{m} \left( \frac{h_{n+1} + h_n}{2} \right) - g
\end{array}
\right.
\label{eq:newton-sp-scheme}
\end{equation}
こいつは幸いにも線形な式なので、キレイに変形できるはずだ. やってみると、まず、簡単のために $\tau = \Delta/2$ とおいて
$$
\left\{\begin{array}{rcl}
\displaystyle h_{n+1} - \tau v_{n+1} & = & \displaystyle h_n + \tau v , \cr
\displaystyle \frac{k}{m}\tau h_{n+1} + v_{n+1} & = & \displaystyle -\frac{k}{m}\tau h + v_n -2\tau g
\end{array}
\right.
$$
となり、これは線形代数の記号では
\begin{equation}
\left(
\begin{array}{cc}
1 & -\tau \cr
\displaystyle \frac{k}{m}\tau & 1
\end{array}
\right)
%
\left(
\begin{array}{c}
h_{n+1} \cr
v_{n+1}
\end{array}
\right)
=
\left(
\begin{array}{cc}
1 & \tau \cr
\displaystyle -\frac{k}{m}\tau & 1
\end{array}
\right)
\left(
\begin{array}{c}
h_n \cr
v_n
\end{array}
\right)
-
\left(
\begin{array}{c}
0 \cr
2\tau g
\end{array}
\right)
\end{equation}
となる. よって、定数部分をわかりやすく
$$ A = \left(\begin{array}{cc} 1 & -\tau \cr \displaystyle \frac{k}{m}\tau & 1 \end{array}\right), $$
$$ B = \left(\begin{array}{cc} 1 & \tau \cr \displaystyle -\frac{k}{m}\tau & 1 \end{array}\right), $$
$$ b = \left(\begin{array}{c} 0 \cr 2\tau g \end{array}\right) $$
とおくと、この数値計算式は
$$ \left( \begin{array}{c} h_{n+1} \cr v_{n+1} \end{array} \right) = A^{-1} \left\{ B \left(\begin{array}{c} h_n \cr v_n \end{array}\right) - b \right\} $$
と書けることになり、シンプルに解けることがわかる.
さてあとはプログラムだ.
まず適当に定義をして、
|
|
続けて、$A, B, b$ を定義してしまおう.
|
|
すると、この近似計算式の 1step 分はいきなり次のように書けてしまう.
|
|
onestep (generic function with 1 method)
あとはいつものように計算するだけだ.
|
|
プロット用にデータを切り出して、
|
|
まずは近似解そのものをプロット.
|
|
うむ.うまくいっているようだな.
ではエネルギーも.
|
|
GKS: Rectangle definition is invalid in routine SET_WINDOW GKS: Rectangle definition is invalid in routine SET_WINDOW GKS: Rectangle definition is invalid in routine SET_WINDOW GKS: Rectangle definition is invalid in routine SET_WINDOW
値の変化が乏しすぎてプロットに失敗するようだ. というわけで初期値からのズレ、をプロットさせよう.
|
|
エネルギー値は 11桁ほど保たれていることがわかる.ふむ、これは良い.
一応、相図もプロットしておこう.目で見てずれがわかるとも思えないが.
|
|
というわけで、最後の「謎」の近似式だとだいぶ良いことがわかる. さて、これはいったいどういう仕組なのだろう?
Report No.09 自力でエネルギー $E(h)$ がもとの運動方程式に従うと保存されることを確認しよう.
$h(t)$ が元の二階常微分方程式である運動方程式 ($\ref{eq:newton-problem}$) の厳密解であるとき、 $h$ のみで書かれた全エネルギー $E(h)$ ($\ref{eq:energy-h}$)の時間微分$\displaystyle \frac{dE}{dt}$ を自分で手で計算し、確かにこれがゼロになることを確認しよう