ふくふくHukuhuku Inc.
EP.13STEM対象: 高2以上 16分公開: 2026-05-10

核分裂連鎖反応をPythonで動かす:中性子・臨界質量・元素別比較

教科書の「連鎖反応」を、自分のパソコンの中で実際に起こします。中性子をランダムウォークさせ、原子核に当たれば分裂、新しい中性子が飛び出す。U-235・Pu-239 などの元素別に、なぜ天然ウランでは爆発しないのか、なぜ臨界質量があるのかが、絵と数字で見えてきます。

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

高校物理の最後に出てくる「原子核」。陽子・中性子・核分裂・連鎖反応 ── 言葉は知っていても、何が「連鎖」なのか、なぜ「」という量があるのか、教科書を読むだけだと分かりにくい。実際にコンピュータの中で中性子を飛ばして、原子核にぶつけて、連鎖反応を起こすと、これらが一気に繋がります。

今回のゴール

① 中性子1個 → 核分裂 → 新しい中性子が複数飛び出す、というルールを実装する。② 「k因子(中性子が次世代で何倍になるか)」がなぜ重要か。③ U-235 / U-238 / Pu-239 / U-233 / Th-232 を比べて、なぜ天然ウランでは爆発しないのか。④ 臨界質量・制御棒の本当の役割。

前置き

本記事は教育目的の物理シミュレーションです。実際の核兵器設計には、爆縮レンズ・タンパー・正確な幾何形状・密度設計など、ここでは触れない要素が決定的に重要で、本記事のシミュレーションでは到達しません。あくまで「教科書の連鎖反応がコードで立ち上がる」体験のために書いています。

Step 0: 教科書のおさらい — 中性子と核分裂

核分裂は、ウランやプルトニウムの原子核に中性子が当たると、原子核が真っ二つに割れて、新しい中性子を平均 ν 個放出する現象。この新しい中性子が他の原子核にぶつかれば、また分裂が起こる。ぶつからずに飛び去ったり、別の物質に吸収されればそこで終わる。

重要な数字: - 核分裂断面積 σ(barn 単位、1 barn = 10⁻²⁴ cm²)= ぶつかりやすさ - 平均放出中性子数 ν(1回の分裂で生まれる中性子数) - k因子 = (新しく生まれる中性子) / (元の中性子) ─ k>1 なら指数増加(爆発的)、k=1 なら定常(原子炉)、k<1 なら減衰

実測値(熱中性子に対して)

U-235: σ_f = 583 barn, ν = 2.42 / Pu-239: σ_f = 750 barn, ν = 2.87 / U-233: σ_f = 530 barn, ν = 2.49 / U-238: σ_f ≈ 0.00002 barn(ほぼ反応しない)/ Th-232: σ_f ≈ 0(直接は分裂しない、増殖して U-233 に変わる)

Step 1: 中性子のランダムウォーク

中性子は質量を持つ粒子、媒質中を直進し、原子核にぶつかると散乱される。まずは2D の箱の中で、1個の中性子をランダムに動かしてみます。

1個の中性子の軌跡
Python
import numpy as npimport matplotlib.pyplot as plt
np.random.seed(2)L = 10.0steps = 200
pos = np.array([5.0, 5.0])           # 中央スタートangle = np.random.uniform(0, 2*np.pi)v = np.array([np.cos(angle), np.sin(angle)])trajectory = [pos.copy()]
for _ in range(steps):    pos = pos + v * 0.1    # 壁で反射(簡略化)    if pos[0] < 0 or pos[0] > L:        v[0] *= -1    if pos[1] < 0 or pos[1] > L:        v[1] *= -1    # ときどきランダム散乱    if np.random.random() < 0.05:        angle = np.random.uniform(0, 2*np.pi)        v = np.array([np.cos(angle), np.sin(angle)])    trajectory.append(pos.copy())
trajectory = np.array(trajectory)plt.figure(figsize=(6, 6))plt.plot(trajectory[:, 0], trajectory[:, 1], lw=0.8, color="goldenrod")plt.scatter(*trajectory[0], c="green", s=100, label="start", zorder=5)plt.scatter(*trajectory[-1], c="red", s=100, label="end", zorder=5)plt.xlim(0, L); plt.ylim(0, L)plt.title("Step 1: A single neutron's path")plt.legend(); plt.grid(alpha=0.3)plt.show()
10x10の箱の中を1個の中性子がランダムに動き回る軌跡
中性子は媒質中を直進し、たまに散乱されて方向を変える

Step 2: 原子核を置いて衝突 → 核分裂

次に、箱の中にウラン原子核(U-235)を散りばめます。中性子が原子核の近くを通ると確率的に 核分裂 が起こり、その原子核は消えて、平均 ν=2.42 個の新しい中性子が飛び出します。

連鎖反応の中核ロジック
Python
import numpy as np
# 原子核(fissile nuclei)N_NUCLEI = 300L = 10.0nuclei = np.random.rand(N_NUCLEI, 2) * L
# 元素パラメータ(U-235)P_FISSION = 0.95   # 衝突距離内に来たときの分裂確率(規格化)NU = 2.42          # 1分裂で出る中性子の平均数R_HIT = 0.25       # 「衝突」と判定する距離
# 中性子の状態(pos, vel)def make_neutron(pos):    angle = np.random.uniform(0, 2*np.pi)    return [pos.copy(), np.array([np.cos(angle), np.sin(angle)])]
neutrons = [make_neutron(np.array([5.0, 5.0]))]
def step_world(neutrons, nuclei):    new_neutrons = []    survived_nuclei_mask = np.ones(len(nuclei), dtype=bool)    for pos, vel in neutrons:        pos += vel * 0.1        # 箱を出たら消える(漏洩)        if not (0 <= pos[0] <= L and 0 <= pos[1] <= L):            continue        # 原子核との衝突判定        if len(nuclei) > 0:            d2 = np.sum((nuclei - pos)**2, axis=1)            hit = np.argmin(d2)            if d2[hit] < R_HIT**2 and survived_nuclei_mask[hit]:                if np.random.random() < P_FISSION:                    # 核分裂発生 ─ 中性子を ν 個生成(ポアソン)                    n_out = np.random.poisson(NU)                    survived_nuclei_mask[hit] = False                    for _ in range(n_out):                        new_neutrons.append(make_neutron(pos))                    continue   # この中性子は消費された        new_neutrons.append([pos, vel])    return new_neutrons, nuclei[survived_nuclei_mask]
# 200 ステップ走らせるcounts = []for t in range(200):    neutrons, nuclei = step_world(neutrons, nuclei)    counts.append(len(neutrons))    if len(neutrons) == 0:        break
ポアソン分布で中性子数を決める理由

現実の核分裂では1回ごとに 0〜6 個程度の中性子が確率的に放出されます。平均が ν の ポアソン分布 で近似するのが一般的。このランダム性が「臨界点」付近で本質的に効きます。

Step 3: 連鎖反応のスナップショット

シミュレーションを動かして途中経過を可視化。生き残った原子核(灰色)と中性子(黄色)を時系列で並べます。

t=0, 30, 60, 100 の4枚のスナップショット。原子核が減って中性子が増えていく
連鎖反応の進行:左上 t=0 から右下 t=100 へ。中性子(黄)が増え原子核(灰)が消える

Step 4: 元素別シミュレーション

同じ仕組みで、断面積 σ と ν を変えると、各元素で連鎖反応がどれくらい起こるかを比較できます。「なぜ天然ウラン(99.3% は U-238)では爆発しないか」が一目で分かる場面です。

5つの核燃料候補を比較
Python
# 規格化したシミュレーション用パラメータELEMENTS = {    "U-235":  {"P": 0.78, "nu": 2.42, "color": "tab:blue"},    "Pu-239": {"P": 1.00, "nu": 2.87, "color": "tab:red"},    "U-233":  {"P": 0.71, "nu": 2.49, "color": "tab:green"},    "U-238":  {"P": 0.00003, "nu": 2.5, "color": "tab:gray"},    "Th-232": {"P": 0.0, "nu": 0.0, "color": "tab:olive"},}
def run(element, T_steps=200):    p = ELEMENTS[element]    nuclei = np.random.rand(N_NUCLEI, 2) * L    neutrons = [make_neutron(np.array([5.0, 5.0]))]    counts = []    for _ in range(T_steps):        neutrons, nuclei = step_world_with(neutrons, nuclei, p["P"], p["nu"])        counts.append(len(neutrons))    return counts
plt.figure(figsize=(10, 5))for el, p in ELEMENTS.items():    plt.semilogy(run(el), label=f"{el} (P={p['P']}, ν={p['nu']})", color=p["color"], linewidth=2)plt.xlabel("Time steps"); plt.ylabel("Neutron count (log)")plt.title("Step 4: Chain reaction by element")plt.legend(loc="upper right"); plt.grid(alpha=0.3, which="both")plt.show()
5元素の中性子数推移を片対数で比較。Pu-239とU-235は指数増加、U-238とTh-232は減衰
Pu-239・U-235・U-233 は指数的に中性子が増える ─ 連鎖反応 / U-238・Th-232 はそもそも反応せず減衰

実際の連鎖反応を動画で見る

数値だけだと「指数増加」が伝わりにくいので、シミュレーションを動画にしました。同じ条件・同じ箱で、4元素を比較。中性子(黄〜赤の点)が増えていく様子と、原子核(灰)が消えていく様子を見比べてください。Pu-239 / U-235 はあっという間に中性子だらけになり、U-238 / Th-232 はそもそも反応が起こらず1個目の中性子が箱から漏れて終了します。

Pu-239 の連鎖反応アニメ。中性子が爆発的に増え、原子核がどんどん消えていく
Pu-239(P=1.00, ν=2.87)── 最も激しい連鎖反応。原爆級の挙動
U-235 の連鎖反応アニメ。Pu-239 より少し緩やかだが指数増加
U-235(P=0.78, ν=2.42)── 連鎖反応するが Pu-239 より緩やか
U-238 で中性子1個が箱から漏れて終了。連鎖反応起こらず
U-238(P≈0)── 熱中性子に対しては事実上反応しない。中性子は壁で反射してそのまま漏れる
Th-232 で中性子1個が漏れて終了。連鎖反応なし
Th-232(直接の核分裂なし)── 中性子吸収して U-233 に変わる「増殖」が必要(自由研究テーマ②)
「天然ウラン99.3%が U-238」の意味

上のアニメを並べて見ると、なぜ天然ウラン(U-238 が 99.3%)で核兵器が作れないかが直感できます。1000個の原子核のうち 993個が「邪魔者」として中性子を漏らしてしまうので、連鎖反応が続きません。ウラン濃縮= U-235 の比率を 0.7% から 90%+ に高める作業 = 上の Pu-239 / U-235 のアニメに状況を近づける作業、です。

天然ウランで核兵器が作れない理由

天然ウランは 99.3% が U-238、わずか 0.7% が U-235。U-238 は熱中性子にほぼ反応しないので、99.3% の原子核がただの「邪魔者」になり連鎖反応が続かない。ウラン濃縮が政治的問題になる本質は、この U-235 の割合を高める作業の難しさにあります。

Step 5: 臨界 ─ k因子の物理的意味

k = 次世代の中性子数 / 現世代の中性子数。k > 1 なら指数的に増える(爆発的)、k = 1 なら定常運転(原子炉)、k < 1 なら減衰。同じ U-235 でも、原子核の密度や箱のサイズ(漏洩率)を変えると k が変わります。

k=0.7 / k=1.0 / k=1.5 を再現
Python
# 原子核密度を変えて 3 パターンdensities = {"sub-critical (k<1)": 100, "critical (k≈1)": 250, "super-critical (k>1)": 500}
plt.figure(figsize=(10, 5))for label, n in densities.items():    nuclei = np.random.rand(n, 2) * L    neutrons = [make_neutron(np.array([5.0, 5.0]))]    counts = []    for _ in range(200):        neutrons, nuclei = step_world(neutrons, nuclei)        counts.append(len(neutrons))        if len(neutrons) > 5000:            break    plt.semilogy(counts, label=label, linewidth=2)plt.xlabel("Time steps"); plt.ylabel("Neutron count (log)")plt.title("Step 5: Three regimes ─ subcritical, critical, supercritical")plt.legend(); plt.grid(alpha=0.3, which="both")plt.show()
k<1で減衰、k≒1で定常、k>1で指数増加の3本のカーブを片対数で比較
燃料の密度(≒質量)を変えただけで、減衰/定常/爆発的増加が切り替わる ─ これが「臨界質量」
原子炉と原爆の違い

原子炉は k=1 で運転する装置(一定の中性子数を維持)/ 原爆は k>1 を瞬間的に作って指数増加させる装置。物理は同じ。形状・密度・反射材で k を制御するか暴走させるか、その違いだけです。

Step 6: 制御棒で k を 1 に戻す

原子炉の制御棒は、中性子をたくさん吸収する材質(カドミウム、ボロンなど)でできています。シミュレーションでも「中性子が制御棒の領域に入ったら消滅」というルールを足すと、暴走していた連鎖反応を k=1 に持ち込めます。

制御棒の領域を追加
Python
# 制御棒:箱の x=4〜5 の領域に入ったら中性子は吸収def step_with_control_rod(neutrons, nuclei):    new_neutrons = []    survived = np.ones(len(nuclei), dtype=bool)    for pos, vel in neutrons:        pos += vel * 0.1        if not (0 <= pos[0] <= L and 0 <= pos[1] <= L):            continue        if 4 < pos[0] < 5:    # ← 制御棒で吸収            continue        # ... 通常の核分裂判定 ...        new_neutrons.append([pos, vel])    return new_neutrons, nuclei[survived]
制御棒なしでは指数増加、ありでは定常運転に落ち着く2本のカーブ
制御棒(中性子吸収)を入れた瞬間、暴走が止まり定常運転に

自由研究の提案

① 減速材の効果: 中性子は速いままだと U-235 とも反応しにくい。水・黒鉛などの減速材で「熱中性子」にすることで反応性が大きく上がる。シミュレーションでも「衝突ごとに速度を 0.7 倍に減速」させると変化が見える。 ② トリウム炉: Th-232 は直接分裂しないが、中性子を吸収して U-233(強い核燃料)に変わる。「Th + n → U-233」のルールを足して、トリウム燃料サイクルを再現してみる。 ③ 反射材: 箱の壁を「反射壁」にすると、漏洩する中性子が戻ってきて k が上がる。タンパーと呼ばれる現実の反射材の役割を確認できる。 ④ 遅発中性子: 実際の核分裂では、ν=2.42 のうち 0.65% が「遅発中性子」(数秒〜数分遅れて出る)。これが原子炉の制御を可能にしている本質。シミュレーションで「ν のうち 1% を遅延 100 ステップで放出」ルールを入れると、なぜ原子炉が制御できるかが分かる。

次回予告

EP.14 はソートアルゴリズム。コンピュータサイエンスの基礎、バブルソートからクイックソート、そして 2022 年に Java で標準採用された Powersort まで。「同じ問題を 100 万倍速く解く」アルゴリズムの発明史を、自分のパソコンで動かしながら追います。

シェア

この記事の感想を教えてください

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

シリーズの外も探す:

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

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

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