高校物理基礎で習う F = ma(力 = 質量 × 加速度)は、宇宙のあらゆる動きを記述する方程式です。今回はこれを Python に書いて、3つのシミュレーションを動かしてみましょう。
Step 1: 自由落下(一定加速度)
重力以外に力が働かない自由落下では、加速度 a = g(9.8 m/s²)で一定。これを オイラー法 で時間刻み dt ごとに更新します。
自由落下
Python
import numpy as npimport matplotlib.pyplot as pltfrom matplotlib.animation import FuncAnimationfrom IPython.display import HTML
g = 9.8dt = 0.05
# 初期状態y = 100 # 高さvy = 0 # 速度
fig, ax = plt.subplots(figsize=(4, 8))ax.set_xlim(-1, 1); ax.set_ylim(0, 110)ball, = ax.plot([0], [y], "o", markersize=20)
def step(frame): global y, vy vy -= g * dt # 速度の更新 y += vy * dt # 位置の更新 if y < 0: y = 0; vy = -vy * 0.7 # 反発係数 0.7 ball.set_data([0], [y]) return ball,
ani = FuncAnimation(fig, step, frames=300, interval=30, blit=True)HTML(ani.to_jshtml())Step 2: 斜面を滑る物体(摩擦あり)
斜面を滑る物体には、重力の斜面成分 と 摩擦力 が働きます:
- 斜面方向の重力 = mg sin θ
- 斜面に垂直な抗力 = mg cos θ
- 摩擦力 = μ × 抗力 = μ mg cos θ(運動方向と逆)
- 合力 = mg(sin θ - μ cos θ)
斜面シミュレーション(摩擦あり)
Python
import numpy as npimport matplotlib.pyplot as pltfrom ipywidgets import interact, FloatSlider
@interact(theta_deg=FloatSlider(min=0, max=80, value=30, description="角度 θ (度)"), mu=FloatSlider(min=0, max=1, step=0.05, value=0.2, description="摩擦係数 μ"))def simulate(theta_deg, mu): g = 9.8 theta = np.radians(theta_deg) # 斜面方向の加速度 a = g * (np.sin(theta) - mu * np.cos(theta))
# 結果のプロット if a <= 0: print(f"加速度 = {a:.2f} m/s² → 動かない(静止摩擦が勝つ)") else: # 1秒後の速度・位置 t_arr = np.linspace(0, 3, 50) v = a * t_arr s = 0.5 * a * t_arr**2 plt.figure(figsize=(10, 4)) plt.subplot(1, 2, 1); plt.plot(t_arr, v); plt.xlabel("時間"); plt.ylabel("速度"); plt.title("速度の変化") plt.subplot(1, 2, 2); plt.plot(t_arr, s); plt.xlabel("時間"); plt.ylabel("移動距離"); plt.title("位置の変化") plt.tight_layout(); plt.show() print(f"加速度 = {a:.2f} m/s²")Step 3: 振り子(非線形運動)
振り子は 微小角の近似で単振動 ですが、大きく振ると非線形になります。両方を比較してみます。
振り子(線形 vs 非線形)
Python
import numpy as npimport matplotlib.pyplot as plt
g = 9.8L = 1.0 # 長さ 1mtheta0 = np.radians(60) # 初期角度 60度(大きい!)dt = 0.01total = 5.0
# 1. 線形近似(sin θ ≈ θ)theta_lin = theta0; omega_lin = 0t = []; theta_lin_arr = []t_now = 0while t_now < total: alpha = -g / L * theta_lin # 線形 omega_lin += alpha * dt theta_lin += omega_lin * dt t.append(t_now); theta_lin_arr.append(np.degrees(theta_lin)) t_now += dt
# 2. 非線形(実際の振り子)theta_nonlin = theta0; omega_nonlin = 0theta_nonlin_arr = []t_now = 0while t_now < total: alpha = -g / L * np.sin(theta_nonlin) # 非線形 omega_nonlin += alpha * dt theta_nonlin += omega_nonlin * dt theta_nonlin_arr.append(np.degrees(theta_nonlin)) t_now += dt
plt.figure(figsize=(10, 4))plt.plot(t, theta_lin_arr, label="線形近似(教科書)")plt.plot(t, theta_nonlin_arr, label="非線形(実際)", linestyle="--")plt.xlabel("時間 (秒)"); plt.ylabel("角度 (度)")plt.legend(); plt.title("初期角度60度の振り子")plt.show()
発見
初期角度を60度にすると、線形近似と非線形で周期が違うことが見えます。教科書の「振り子の周期 T = 2π√(L/g) は、振幅が小さいときの近似」という注釈の意味が、グラフで分かる。
に発展問題を頼む
prompt
物理基礎の「ばね振り子」と「単振り子」の違いを Python で可視化したいです。
要件:
- 同じ周期になる条件下でアニメで並べて表示
- グラフは時間 vs 位置
- 単振り子は微小角の近似で
- ばね振り子は F = -kx
- 教科書の式と Python のコードを並べて、対応関係を解説 想定される実行結果(例示)
## ばね振り子 vs 単振り子(同じ周期で比較)
### 教科書の式
- ばね振り子: F = -kx, T = 2π√(m/k)
- 単振り子(微小角): F = -mg sin θ ≈ -mgθ, T = 2π√(L/g)
→ 同じ周期にするには L/g = m/k
### コード
```python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# 同じ周期にする設定
m, k = 1, 9.8 # ばね振り子: T = 2π√(1/9.8) ≈ 2.0s
L = 1.0 # 単振り子: T = 2π√(1/9.8) ≈ 2.0s
# シミュレーション
def simulate(force_fn, x0, dt=0.01, total=5):
x, v = x0, 0
xs = []
t = 0
while t < total:
F = force_fn(x)
v += F / 1.0 * dt
x += v * dt
xs.append(x)
t += dt
return xs
x_spring = simulate(lambda x: -k * x, 0.5)
x_pend = simulate(lambda th: -9.8 / L * th, np.radians(30))
t_arr = np.linspace(0, 5, len(x_spring))
plt.figure(figsize=(10, 4))
plt.plot(t_arr, x_spring, label="ばね振り子")
plt.plot(t_arr, np.degrees(x_pend) / 30, label="単振り子(規格化)", linestyle="--")
plt.legend(); plt.xlabel("時間"); plt.ylabel("変位(規格化)")
plt.show()
```
→ 同じ周期で振動。これが「**任意の単振動は同じ形の式で書ける**」という統一視点。次回予告
EP.04 は天文学。太陽系の惑星を Python で公転 させて、ケプラーの法則を体感します。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。