運動量保存則はエネルギー保存則と並ぶ物理学の根幹的な法則です。特に衝突問題では、力の時間変化の詳細がわからなくても、衝突前後の状態を結びつけることができます。
本記事の内容
- 運動量の定義と力積
- 運動量保存則の導出
- 弾性衝突と非弾性衝突
- 反発係数
- 2体衝突の速度公式
- Pythonでの衝突シミュレーション
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
運動量の定義
質量 $m$、速度 $\bm{v}$ の質点の運動量(momentum)は次のように定義されます。
$$ \bm{p} = m\bm{v} $$
運動量はベクトル量であり、運動の「勢い」を表します。質量が大きいほど、速度が大きいほど、運動量は大きくなります。
力積と運動量の関係
ニュートンの第2法則は運動量を用いて次のように書けます。
$$ \bm{F} = m\bm{a} = m\frac{d\bm{v}}{dt} = \frac{d(m\bm{v})}{dt} = \frac{d\bm{p}}{dt} $$
両辺を時間で積分すると力積(impulse)が得られます。
$$ \begin{align} \int_{t_1}^{t_2} \bm{F} \, dt &= \int_{t_1}^{t_2} \frac{d\bm{p}}{dt} \, dt \\ &= \bm{p}(t_2) – \bm{p}(t_1) \\ &= \Delta\bm{p} \end{align} $$
$$ \boxed{\bm{J} = \int_{t_1}^{t_2} \bm{F} \, dt = \Delta\bm{p}} $$
力積は運動量の変化に等しいという関係です。短時間に大きな力が作用する衝突現象では、この関係が特に有用です。
運動量保存則の導出
2つの質点が相互作用する系を考えます。質点1が質点2から受ける力を $\bm{F}_{12}$、質点2が質点1から受ける力を $\bm{F}_{21}$ とします。
ニュートンの第3法則(作用・反作用の法則)より:
$$ \bm{F}_{12} = -\bm{F}_{21} $$
各質点の運動方程式は:
$$ \frac{d\bm{p}_1}{dt} = \bm{F}_{12}, \quad \frac{d\bm{p}_2}{dt} = \bm{F}_{21} $$
両辺を加えると:
$$ \begin{align} \frac{d\bm{p}_1}{dt} + \frac{d\bm{p}_2}{dt} &= \bm{F}_{12} + \bm{F}_{21} \\ \frac{d}{dt}(\bm{p}_1 + \bm{p}_2) &= \bm{0} \end{align} $$
よって、外力がない系では全運動量は一定です。
$$ \boxed{\bm{p}_1 + \bm{p}_2 = m_1\bm{v}_1 + m_2\bm{v}_2 = \text{const}} $$
これが運動量保存則です。$N$ 個の質点系に拡張すると:
$$ \sum_{i=1}^N \bm{p}_i = \text{const} \quad (\text{外力が0のとき}) $$
弾性衝突と非弾性衝突
衝突は力学的エネルギーが保存されるかどうかで分類されます。
| 分類 | 運動量 | 運動エネルギー | 例 |
|---|---|---|---|
| 弾性衝突 | 保存 | 保存 | ビリヤード球 |
| 非弾性衝突 | 保存 | 一部損失 | 自動車の衝突 |
| 完全非弾性衝突 | 保存 | 最大損失 | 粘土球の衝突(合体) |
反発係数
反発係数(coefficient of restitution)$e$ は衝突の「跳ね返り具合」を表します。
$$ \boxed{e = -\frac{v_1′ – v_2′}{v_1 – v_2} = \frac{\text{衝突後の相対速度}}{\text{衝突前の相対速度}}} $$
ここで $v_1, v_2$ は衝突前、$v_1′, v_2’$ は衝突後の速度です(1次元)。
- $e = 1$: 弾性衝突(エネルギー保存)
- $0 < e < 1$: 非弾性衝突
- $e = 0$: 完全非弾性衝突(合体)
2体衝突の速度公式
1次元の2体衝突を考えます。運動量保存則と反発係数の定義を連立させます。
$$ m_1 v_1 + m_2 v_2 = m_1 v_1′ + m_2 v_2′ \quad \cdots (1) $$
$$ e = -\frac{v_1′ – v_2′}{v_1 – v_2} \quad \cdots (2) $$
式(2)より:
$$ v_1′ – v_2′ = -e(v_1 – v_2) \quad \cdots (2′) $$
式(1)より:
$$ m_1(v_1 – v_1′) = m_2(v_2′ – v_2) \quad \cdots (1′) $$
式(2′)から $v_2′ = v_1′ + e(v_1 – v_2)$ を式(1)に代入すると:
$$ \begin{align} m_1 v_1 + m_2 v_2 &= m_1 v_1′ + m_2 [v_1′ + e(v_1 – v_2)] \\ m_1 v_1 + m_2 v_2 &= (m_1 + m_2) v_1′ + m_2 e(v_1 – v_2) \end{align} $$
$v_1’$ について整理すると:
$$ \boxed{v_1′ = \frac{m_1 v_1 + m_2 v_2 + m_2 e(v_2 – v_1)}{m_1 + m_2}} $$
同様に $v_2’$ は:
$$ \boxed{v_2′ = \frac{m_1 v_1 + m_2 v_2 + m_1 e(v_1 – v_2)}{m_1 + m_2}} $$
特殊な場合
弾性衝突($e=1$) の場合:
$$ v_1′ = \frac{(m_1 – m_2)v_1 + 2m_2 v_2}{m_1 + m_2}, \quad v_2′ = \frac{(m_2 – m_1)v_2 + 2m_1 v_1}{m_1 + m_2} $$
等質量の弾性衝突($m_1 = m_2, e=1$) の場合:
$$ v_1′ = v_2, \quad v_2′ = v_1 $$
速度が完全に交換されます。
Pythonでの実装
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
from matplotlib.animation import FuncAnimation
# --- 2体衝突の速度公式 ---
def collision_velocity(m1, m2, v1, v2, e):
"""衝突後の速度を計算"""
v1_after = (m1*v1 + m2*v2 + m2*e*(v2 - v1)) / (m1 + m2)
v2_after = (m1*v1 + m2*v2 + m1*e*(v1 - v2)) / (m1 + m2)
return v1_after, v2_after
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
# --- (1) 反発係数ごとの衝突後速度 ---
m1, m2 = 2.0, 1.0
v1, v2 = 3.0, -1.0
e_values = np.linspace(0, 1, 100)
v1_after = [(m1*v1 + m2*v2 + m2*e*(v2 - v1)) / (m1 + m2) for e in e_values]
v2_after = [(m1*v1 + m2*v2 + m1*e*(v1 - v2)) / (m1 + m2) for e in e_values]
axes[0].plot(e_values, v1_after, 'b-', linewidth=2, label='$v_1\'$')
axes[0].plot(e_values, v2_after, 'r-', linewidth=2, label='$v_2\'$')
axes[0].axhline(y=v1, color='b', linestyle='--', alpha=0.4, label=f'$v_1 = {v1}$')
axes[0].axhline(y=v2, color='r', linestyle='--', alpha=0.4, label=f'$v_2 = {v2}$')
axes[0].set_xlabel('反発係数 $e$')
axes[0].set_ylabel('衝突後の速度 [m/s]')
axes[0].set_title(f'反発係数と衝突後速度 ($m_1={m1}$, $m_2={m2}$)')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# --- (2) エネルギー損失 ---
KE_before = 0.5*m1*v1**2 + 0.5*m2*v2**2
KE_loss = []
for e in e_values:
v1a, v2a = collision_velocity(m1, m2, v1, v2, e)
KE_after = 0.5*m1*v1a**2 + 0.5*m2*v2a**2
KE_loss.append((KE_before - KE_after) / KE_before * 100)
axes[1].plot(e_values, KE_loss, 'g-', linewidth=2)
axes[1].set_xlabel('反発係数 $e$')
axes[1].set_ylabel('エネルギー損失 [%]')
axes[1].set_title('反発係数と運動エネルギー損失')
axes[1].grid(True, alpha=0.3)
axes[1].set_ylim(0, max(KE_loss)*1.1)
# --- (3) 衝突シミュレーション(位置の時間変化) ---
m1, m2 = 1.0, 2.0
v1_init, v2_init = 4.0, -1.0
x1_init, x2_init = 0.0, 5.0
e = 0.8
dt = 0.01
t_max = 4.0
t = np.arange(0, t_max, dt)
x1 = np.zeros_like(t)
x2 = np.zeros_like(t)
x1[0], x2[0] = x1_init, x2_init
vel1, vel2 = v1_init, v2_init
for i in range(1, len(t)):
x1[i] = x1[i-1] + vel1*dt
x2[i] = x2[i-1] + vel2*dt
# 衝突判定(質点が同じ位置に達したとき)
if x1[i] >= x2[i] and vel1 > vel2:
vel1, vel2 = collision_velocity(m1, m2, vel1, vel2, e)
axes[2].plot(t, x1, 'b-', linewidth=2, label=f'質点1 ($m_1={m1}$)')
axes[2].plot(t, x2, 'r-', linewidth=2, label=f'質点2 ($m_2={m2}$)')
axes[2].set_xlabel('時間 [s]')
axes[2].set_ylabel('位置 [m]')
axes[2].set_title(f'衝突シミュレーション ($e={e}$)')
axes[2].legend()
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('momentum_conservation.png', dpi=150, bbox_inches='tight')
plt.show()
# 数値確認
v1a, v2a = collision_velocity(1.0, 2.0, 4.0, -1.0, 0.8)
print(f"衝突後: v1' = {v1a:.2f} m/s, v2' = {v2a:.2f} m/s")
p_before = 1.0*4.0 + 2.0*(-1.0)
p_after = 1.0*v1a + 2.0*v2a
print(f"運動量: 衝突前 = {p_before:.2f}, 衝突後 = {p_after:.2f}")
まとめ
本記事では、運動量保存則と衝突問題について解説しました。
- 運動量: $\bm{p} = m\bm{v}$、力積は運動量変化に等しい
- 運動量保存則: 外力がない系では $\sum \bm{p}_i = \text{const}$
- 反発係数 $e$ で衝突の種類が決まる($e=1$: 弾性、$e=0$: 完全非弾性)
- 2体衝突の速度公式は運動量保存と反発係数の連立で導出
- エネルギー損失は $e$ が小さいほど大きい
次のステップとして、以下の記事も参考にしてください。