シミュレーションで使う積分幅(時間刻み)の決め方 ~ 小さくすれば良いわけじゃない!
シミュレーションで微分方程式を扱うとき、数式と同じくらい 積分幅 も大切です。以前、このような記事を作成しました。
この記事のように、時間とともに状態が推移する物理モデルの場合、積分幅である 時間刻み $${dt}$$ を小さくすれば計算の精度は良くなります。しかし、繰り返し計算が増えるので、計算にかかる時間も長くなります。
逆に、時間刻み $${dt}$$ を大きくすれば繰り返し計算が減るので、計算にかかる時間は短くなります。しかし、計算の誤差が大きくなり精度が悪くなります。
このように、計算精度と計算時間にはトレードオフの関係があります。
この積分幅(時間刻み $${dt}$$ )をどのように決めるのかは、微分方程式を扱うシミュレーションでは避けて通れません。
今回は、この積分幅(時間刻み $${dt}$$ )の決め方をテーマとして取り上げます。
✅ 対象とする現象
積分幅(時間刻み $${dt}$$ )の決め方の例として扱うのは、質点の自由落下というシンプルな現象です。
自由落下とは、重力という一定の力が質点に作用し、その結果として加速度・速度・位置が時間とともに変化していく現象です。このように時間とともに状態が変化する現象は、数値シミュレーションの基本題材としてよく使われます。特に自由落下は、厳密解(数式で厳密に解ける解)が存在するので、シミュレーション結果と照らし合わせて真の誤差を確認しやすいという利点があります。
そこで自由落下を対象として、積分幅である時間刻み $${dt}$$ を変えて比較し、計算誤差と計算時間を合わせてチェックしながら、適正値を探っていきます。
✅ 現象をモデル化
自由落下の運動方程式そのものについては、下の記事で詳しく扱いました。
ここでは数式の導出は省略し、時間刻み $${dt}$$ の検討に焦点をあてます。
運動方程式のような微分方程式を数値計算で解くとき、連続的に変化する解を「微小区間ごとのステップ」に区切って計算します。運動方程式の場合、このステップに相当するのが時間刻み $${dt}$$ です。この $${dt}$$ が大きいと曲線的な変化を直線で近似してしまい、誤差が大きくなります。一方で、$${dt}$$ を小さくすると近似の精度は良くなりますが、その分だけ計算回数が増え、計算にかかる時間が長くなります。
そのため、$${dt}$$ の適正値を決めるとき、次の順で考えます。
誤差の許容範囲を決める
目的に応じて、どの程度の誤差なら許容できるかをあらかじめ設定する。収束を確認する
時間刻み $${dt}$$ を 1/10 にしても、結果の変化が誤差の許容範囲内に収まるなら、その $${dt}$$ は十分に小さいと判断できる。精度と効率のバランスを取る
小さすぎる $${dt}$$ は計算時間が無駄に長くなる。誤差の許容範囲を満たす中で、できるだけ大きな $${dt}$$ を選ぶ。計算時間を実用レベルに抑える
数値計算法には色々と種類がある。誤差の許容範囲を満たした計算をするときに必要な時間が長すぎる場合は、数値計算法を見直して、再度、2. 収束を確認する へ戻る。
以上を踏まえ、検討条件を次のようにする。
シミュレーション時間:
$${T=1.0\ \mathrm{s}}$$
許容誤差 $${x_\varepsilon}$$:
$${x_\varepsilon=0.0001\ \mathrm{m} (=0.1 \ \mathrm{mm})}$$
※実生活の中で十分に小さい値として設定
※計算したい変位$${x}$$を誤差計算の対象とした。
刻み時間:
$${dt = 0.1 = 10^{-1}\ \mathrm{s}}$$
※計算の繰り返し回数は少ないが、誤差が大きい可能性あり$${dt = 0.01 = 10^{-2}\ \mathrm{s}}$$
$${dt = 0.001 = 10^{-3}\ \mathrm{s}}$$
$${dt = 0.0001 = 10^{-4}\ \mathrm{s}}$$
$${dt = 0.00001 = 10^{-5}\ \mathrm{s}}$$
$${dt = 0.000001 = 10^{-6}\ \mathrm{s}}$$
※誤差がほぼ無視できるが、計算の繰り返し回数は多い
✅ Pythonで解く
時間刻み $${dt}$$ を変えてシミュレーションを行います。
参考までに、厳密解(数式を近似しないで解いた値)は次のとおりです。
落下距離 $${x_{exact} = 4.903325 \ \mathrm{m}}$$
真の誤差は、シミュレーション結果を厳密解と比較すれば求められます。しかし、実際の問題では厳密解を求められないケースばかりなので、この真の誤差は不明とした前提で検討していきます。
▶ Pythonスクリプト
下の記事で作成したPythonスクリプトに、計算時間を出力するためのコードを追加しました。
そのPythonスクリプトがこちらです。
▶ シミュレーション結果
$${dt = 10^{-1}\ \mathrm{s}}$$ のとき
・計算時間:$${0.000130}$$ 秒
・落下距離:$${x \simeq 5.933023\ \mathrm{m}}$$$${dt = 10^{-2}\ \mathrm{s}}$$ のとき
・計算時間:$${0.000213}$$ 秒
・落下距離:$${x \simeq 5.001881\ \mathrm{m}}$$
※$${dt = 10^{-1}\ \mathrm{s}}$$ との差:
$${|5.001881 - 5.933023| = 0.931142 > x_\varepsilon = 0.0001}$$
×許容誤差 $${x_\varepsilon}$$ を超えている$${dt = 10^{-3}\ \mathrm{s}}$$ のとき
・計算時間:$${0.000949}$$ 秒
・落下距離:$${x \simeq 4.913136\ \mathrm{m}}$$
※$${dt = 10^{-2}\ \mathrm{s}}$$ との差:
$${|4.913136 - 5.001881| = 0.088745 > x_\varepsilon = 0.0001}$$
×許容誤差 $${x_\varepsilon}$$ を超えている$${dt = 10^{-4}\ \mathrm{s}}$$ のとき
・計算時間:$${0.009751}$$ 秒
・落下距離:$${x \simeq 4.904305\ \mathrm{m}}$$
※$${dt = 10^{-3}\ \mathrm{s}}$$ との差:
$${|4.904305 - 4.913136| = 0.008831 > x_\varepsilon = 0.0001}$$
×許容誤差 $${x_\varepsilon}$$ を超えている$${dt = 10^{-5}\ \mathrm{s}}$$ のとき
・計算時間:$${0.096294}$$ 秒
・落下距離:$${x \simeq 4.903324\ \mathrm{m}}$$
※$${dt = 10^{-4}\ \mathrm{s}}$$ との差:
$${|4.903324 - 4.904305| = 0.000981 > x_\varepsilon = 0.0001}$$
×許容誤差 $${x_\varepsilon}$$ を超えている$${dt = 10^{-6}\ \mathrm{s}}$$ のとき
・計算時間:$${1.003567}$$ 秒
・落下距離:$${x \simeq 4.903334\ \mathrm{m}}$$
※$${dt = 10^{-5}\ \mathrm{s}}$$ との差:
$${|4.903334 - 4.903324| = 0.000010 < x_\varepsilon = 0.0001}$$
〇許容誤差 $${x_\varepsilon}$$ の範囲内
以上より、$${dt = 10^{-5}\ \mathrm{s}}$$ が適正値です。
✅ 解説
先ほどの結果からわかるのは、刻み時間 $${dt}$$ を小さくすれば精度が良くなる一方で、計算時間は増えるというシンプルなトレードオフの関係です。
$${dt = 10^{-4}\ \mathrm{s}}$$ 以上では、計算は速いものの誤差が大きく許容範囲を超えてしまいました。
$${dt = 10^{-6}\ \mathrm{s}}$$ では、誤差は非常に小さく精度としては十分ですが、計算時間が長くなりました。
$${dt = 10^{-5}\ \mathrm{s}}$$ では、誤差が許容範囲($${x_\varepsilon=0.0001\ \mathrm{m}}$$)に収まり、計算時間も比較的に短く抑えられました。
ここで重要なのは、より小さい $${dt}$$ を選ぶ必要があるかどうかを、さらに小さい刻み幅との比較で判断することです。
今回であれば、$${dt = 10^{-5}\ \mathrm{s}}$$ と $${dt = 10^{-6}\ \mathrm{s}}$$ の結果を比べ、その違いが許容誤差の範囲内であれば、より大きな $${dt = 10^{-5}\ \mathrm{s}}$$ を採用します。
つまり『許容誤差を満たしつつ、計算時間をできるだけ短くできる』のが、適正な刻み幅です。小さければ安心というわけではなく、必要十分な精度を満たす範囲で大きな刻み幅を選ぶことが重要です。
さらに、今回の結果では $${dt = 10^{-6}\ \mathrm{s}}$$ にすると、かえって厳密解との誤差が大きくなったことに気が付きましたか?
これは、丸め誤差 の影響です。
コンピュータは有限の桁数で数値を扱うため、変数の値が非常に小さくなると、有効桁数に埋もれて正確に加算できなくなります(桁落ち)。さらに、ステップ数も膨大になることで、この誤差が積み重なって累積してしまう、といった現象が起こります。
シミュレーションでは、刻みが大きすぎると離散化誤差、小さすぎても丸め誤差、という二重の計算誤差があることを知っておいてください。
最後に、どうしても許容誤差を満たせない場合は、オイラー法のような単純な手法ではなく、ルンゲ=クッタ法など高精度の数値解法に切り替えることも選択肢となります。
✅ おわりに
今回のテーマは、数値シミュレーションにおける積分幅の決め方でした。
この一例として、時間刻み $${dt}$$ を扱いましたが、結論として大切なのは、誤差の許容範囲をあらかじめ定め、その範囲に収まる中で最も大きな積分幅を選ぶことです。小さくすれば確かに精度は上がりますが、計算時間が無駄に長くなるだけで意味がありません。
今回の検討条件(許容誤差 $${x_\varepsilon=0.0001\ \mathrm{m}}$$)では、$${dt = 10^{-5}\ \mathrm{s}}$$ を使えば十分でした。これ以上小さくしても結果の違いはほとんどなく、計算時間だけが余分にかかるからです。さらに $${dt = 10^{-6}\ \mathrm{s}}$$ では、丸め誤差の影響でむしろ精度が悪化する結果も現れました。
つまり、積分幅は小さければ安心という発想ではなく、必要十分な精度を満たしつつ、効率の良い値を選ぶことが重要です。今回の自由落下は単純な題材ですが、資産運用シミュレーションや他の複雑なシミュレーションであっても、この考え方は同じです。
シミュレーションを活用するときは、常に「適切な誤差の許容範囲」と「計算時間」を意識して、最適な刻み幅を選びましょう!
🔗 続けて読みたい記事
少しでも参考になったと思ったら、
スキやフォローしていただけると、
次の記事を作成する励みになります!
数理テーマ: #数値計算 #積分幅 #シミュレーション精度 #計算時間
いいなと思ったら応援しよう!
もし具体的に何かのお役に立てたなら、チップで応援していただけると励みになります!
いただいたチップは、今後の活動に使わせていただきます😊