ふくふくHukuhuku Inc.
EP.03STEM対象: 中3以上 13分公開: 2026-05-10

落ちる・跳ねる・揺れる:物理シミュレーター

F=ma の方程式が、画面の動くオブジェクトとして見えてくる。自由落下・斜面・振り子の3パターンを実装。

#中高生#物理#力学#シミュレーション
CO📔 Google Colab で開く(上から順にセルを実行)
シェア

高校物理基礎で習う 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()
振り子の角度の時間変化(線形近似と非線形の比較、3つの初期振幅)
実線=非線形(実際)、点線=線形近似。振幅が大きいほど両者がズレる
発見

初期角度を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 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp