発散(div)の定義と物理的意味を完全理解する

ベクトル場のある点で「流体が湧き出しているのか、吸い込まれているのか」を定量的に表す量が 発散(divergence)です。イメージとしては、浴槽の蛇口のような湧き出し点では発散が正、排水口のような吸い込み点では発散が負になります。

発散は電磁気学のガウスの法則($\nabla \cdot \bm{E} = \rho / \varepsilon_0$)、流体力学の連続の式(質量保存則)、熱力学のエネルギー保存則など、物理法則の記述に不可欠な微分演算子です。

本記事の内容

  • 発散の直感的な理解(湧き出しと吸い込み)
  • 発散の数学的定義
  • ガウスの発散定理
  • 発散の物理的応用
  • 具体例と計算
  • Pythonでの発散の可視化

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

発散とは

直感的な理解

ベクトル場 $\bm{F}$ を水の流れだと考えます。空間のある小さな領域に注目したとき:

  • 流出する量が流入する量より多い → 湧き出し(source) → $\mathrm{div}\, \bm{F} > 0$
  • 流入する量が流出する量より多い → 吸い込み(sink) → $\mathrm{div}\, \bm{F} < 0$
  • 流入と流出が等しい → 非圧縮(solenoidal) → $\mathrm{div}\, \bm{F} = 0$

もう少し正確に言うと、発散は「微小体積あたりの正味の流出量」を表します。

微小体積からの導出

点 $(x_0, y_0, z_0)$ を中心とする微小直方体(辺の長さ $\Delta x, \Delta y, \Delta z$)を考えます。$x$ 方向の正味の流出量は:

$$ \begin{align} \Phi_x &\approx F_x(x_0 + \tfrac{\Delta x}{2}, y_0, z_0) \cdot \Delta y \Delta z – F_x(x_0 – \tfrac{\Delta x}{2}, y_0, z_0) \cdot \Delta y \Delta z \\ &\approx \frac{\partial F_x}{\partial x} \Delta x \Delta y \Delta z \end{align} $$

$y$ 方向、$z$ 方向も同様に計算して、正味の総流出量は:

$$ \Phi \approx \left(\frac{\partial F_x}{\partial x} + \frac{\partial F_y}{\partial y} + \frac{\partial F_z}{\partial z}\right) \Delta x \Delta y \Delta z $$

単位体積あたりの流出量($\Delta V = \Delta x \Delta y \Delta z$ で割ったもの)が発散です。

発散の数学的定義

定義

ベクトル場 $\bm{F}(x, y, z) = (F_x, F_y, F_z)$ の 発散(divergence)は:

$$ \begin{equation} \mathrm{div}\, \bm{F} = \nabla \cdot \bm{F} = \frac{\partial F_x}{\partial x} + \frac{\partial F_y}{\partial y} + \frac{\partial F_z}{\partial z} \end{equation} $$

ナブラ演算子 $\nabla$ とベクトル場 $\bm{F}$ の「内積」として表現されます。

$$ \nabla \cdot \bm{F} = \begin{pmatrix} \dfrac{\partial}{\partial x} \\[8pt] \dfrac{\partial}{\partial y} \\[8pt] \dfrac{\partial}{\partial z} \end{pmatrix} \cdot \begin{pmatrix} F_x \\ F_y \\ F_z \end{pmatrix} $$

2次元の場合は:

$$ \nabla \cdot \bm{F} = \frac{\partial F_x}{\partial x} + \frac{\partial F_y}{\partial y} $$

重要な性質

発散はベクトル場からスカラー場を返す演算です。

$$ \nabla \cdot: \text{ベクトル場} \to \text{スカラー場} $$

座標系に依存しない定義

発散は次のように座標系に依存しない形でも定義できます。

$$ \begin{equation} \mathrm{div}\, \bm{F} = \lim_{\Delta V \to 0} \frac{1}{\Delta V} \oint_{\partial V} \bm{F} \cdot d\bm{S} \end{equation} $$

これは「微小体積 $\Delta V$ の表面を通る $\bm{F}$ の正味の流束を体積で割った極限」であり、「単位体積あたりの湧き出し量」という物理的意味を直接反映しています。

ガウスの発散定理

定理

ガウスの発散定理(Gauss’s divergence theorem)は、体積分と面積分を結ぶ定理です。

閉曲面 $\partial V$ で囲まれた領域 $V$ において、ベクトル場 $\bm{F}$ が $V$ 上で $C^1$ 級ならば:

$$ \begin{equation} \oint_{\partial V} \bm{F} \cdot d\bm{S} = \iiint_V (\nabla \cdot \bm{F}) \, dV \end{equation} $$

ここで $d\bm{S} = \bm{n} \, dS$ は外向き法線ベクトル付きの面積要素です。

定理の意味

左辺は「閉曲面 $\partial V$ を通る $\bm{F}$ の総流出量」(面積分)です。右辺は「$V$ 内部での発散の総和」(体積分)です。

つまり、表面を通る正味の流束は、内部の湧き出し量の合計に等しい ということです。水道管の比喩で言えば、「部屋から出ていく水の量」は「部屋の中にあるすべての蛇口から出る水の量の合計」に等しいのです。

導出の概略

領域 $V$ を多数の微小直方体 $\Delta V_k$ に分割します。各微小直方体に対して:

$$ \oint_{\partial \Delta V_k} \bm{F} \cdot d\bm{S} \approx (\nabla \cdot \bm{F})|_k \Delta V_k $$

すべての微小直方体について足し合わせると、隣接する面では流束が打ち消し合い、外側の面のみが残ります。

$$ \begin{align} \sum_k \oint_{\partial \Delta V_k} \bm{F} \cdot d\bm{S} &= \oint_{\partial V} \bm{F} \cdot d\bm{S} \\ \sum_k (\nabla \cdot \bm{F})|_k \Delta V_k &\to \iiint_V (\nabla \cdot \bm{F}) \, dV \end{align} $$

したがって $\oint_{\partial V} \bm{F} \cdot d\bm{S} = \iiint_V (\nabla \cdot \bm{F}) \, dV$ が成り立ちます。

具体例

例1: 放射状ベクトル場

$\bm{F}(x, y, z) = (x, y, z)$ の発散は:

$$ \nabla \cdot \bm{F} = \frac{\partial x}{\partial x} + \frac{\partial y}{\partial y} + \frac{\partial z}{\partial z} = 1 + 1 + 1 = 3 $$

すべての点で $\mathrm{div}\, \bm{F} = 3 > 0$ なので、空間のいたるところで湧き出しています。

検証(ガウスの定理で): 半径 $R$ の球面 $S$ で:

$$ \oint_S \bm{F} \cdot d\bm{S} = \oint_S R \, dS = R \cdot 4\pi R^2 = 4\pi R^3 $$

一方:

$$ \iiint_V 3 \, dV = 3 \cdot \frac{4}{3}\pi R^3 = 4\pi R^3 $$

一致します。

例2: 回転ベクトル場

$\bm{F}(x, y, z) = (-y, x, 0)$ の発散は:

$$ \nabla \cdot \bm{F} = \frac{\partial(-y)}{\partial x} + \frac{\partial x}{\partial y} + \frac{\partial 0}{\partial z} = 0 + 0 + 0 = 0 $$

回転場は湧き出しも吸い込みもなく、$\mathrm{div}\, \bm{F} = 0$ です。このようなベクトル場を ソレノイダル場(solenoidal field)と呼びます。

例3: 点電荷の電場

原点にある点電荷 $q$ が作る電場 $\bm{E} = \frac{q}{4\pi\varepsilon_0} \frac{\bm{r}}{r^3}$ に対して、$r \neq 0$ では $\nabla \cdot \bm{E} = 0$ です。しかし原点($r = 0$)では特異性があり、ガウスの法則は:

$$ \nabla \cdot \bm{E} = \frac{q}{\varepsilon_0} \delta^3(\bm{r}) $$

と、ディラックのデルタ関数を用いて表されます。

物理的応用

連続の式(質量保存則)

流体の密度 $\rho$ と速度場 $\bm{v}$ に対して、質量保存則は:

$$ \begin{equation} \frac{\partial \rho}{\partial t} + \nabla \cdot (\rho \bm{v}) = 0 \end{equation} $$

$\nabla \cdot (\rho \bm{v})$ は単位体積あたりの質量の流出率を表します。

非圧縮性流体

非圧縮性流体($\rho = \mathrm{const.}$)では連続の式から:

$$ \nabla \cdot \bm{v} = 0 $$

これは流体がどこでも湧き出しも吸い込みもしないことを意味します。

Pythonでの実装

発散の数値計算

import numpy as np

def divergence_2d(Fx, Fy, dx, dy):
    """
    2次元ベクトル場の発散を中心差分で数値計算する

    Parameters
    ----------
    Fx, Fy : ndarray, shape (ny, nx)
        ベクトル場の x, y 成分
    dx, dy : float
        格子間隔

    Returns
    -------
    ndarray, shape (ny, nx)
        発散のスカラー場
    """
    dFx_dx = np.gradient(Fx, dx, axis=1)
    dFy_dy = np.gradient(Fy, dy, axis=0)
    return dFx_dx + dFy_dy

# テスト: F = (x, y) → div F = 2
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
dx = x[1] - x[0]
dy = y[1] - y[0]

Fx = X
Fy = Y
div_F = divergence_2d(Fx, Fy, dx, dy)

print(f"F = (x, y)")
print(f"解析的な div F = 2")
print(f"数値的な div F (mean) = {div_F.mean():.6f}")
print(f"数値的な div F (std)  = {div_F.std():.6f}")

発散の可視化

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-3, 3, 200)
y = np.linspace(-3, 3, 200)
X, Y = np.meshgrid(x, y)
dx = x[1] - x[0]
dy = y[1] - y[0]

fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# --- 例1: F = (x, y)(湧き出し場)---
ax = axes[0, 0]
Fx, Fy = X, Y
div_F = divergence_2d(Fx, Fy, dx, dy)

contour = ax.contourf(X, Y, div_F, levels=20, cmap='RdBu_r', alpha=0.7)
plt.colorbar(contour, ax=ax, label='$\\nabla \\cdot \\mathbf{F}$')

skip = 15
ax.quiver(X[::skip, ::skip], Y[::skip, ::skip],
          Fx[::skip, ::skip], Fy[::skip, ::skip],
          color='black', scale=40, width=0.003)
ax.set_title('$\\mathbf{F} = (x, y)$: $\\nabla \\cdot \\mathbf{F} = 2$ (Source)')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')

# --- 例2: F = (-x, -y)(吸い込み場)---
ax = axes[0, 1]
Fx, Fy = -X, -Y
div_F = divergence_2d(Fx, Fy, dx, dy)

contour = ax.contourf(X, Y, div_F, levels=20, cmap='RdBu_r', alpha=0.7)
plt.colorbar(contour, ax=ax, label='$\\nabla \\cdot \\mathbf{F}$')

ax.quiver(X[::skip, ::skip], Y[::skip, ::skip],
          Fx[::skip, ::skip], Fy[::skip, ::skip],
          color='black', scale=40, width=0.003)
ax.set_title('$\\mathbf{F} = (-x, -y)$: $\\nabla \\cdot \\mathbf{F} = -2$ (Sink)')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')

# --- 例3: F = (-y, x)(回転場、div = 0)---
ax = axes[1, 0]
Fx, Fy = -Y, X
div_F = divergence_2d(Fx, Fy, dx, dy)

contour = ax.contourf(X, Y, div_F, levels=20, cmap='RdBu_r', alpha=0.7)
plt.colorbar(contour, ax=ax, label='$\\nabla \\cdot \\mathbf{F}$')

ax.quiver(X[::skip, ::skip], Y[::skip, ::skip],
          Fx[::skip, ::skip], Fy[::skip, ::skip],
          color='black', scale=40, width=0.003)
ax.set_title('$\\mathbf{F} = (-y, x)$: $\\nabla \\cdot \\mathbf{F} = 0$ (Solenoidal)')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')

# --- 例4: F = (x^2, xy)(空間依存の発散)---
ax = axes[1, 1]
Fx = X**2
Fy = X * Y
div_F = divergence_2d(Fx, Fy, dx, dy)

contour = ax.contourf(X, Y, div_F, levels=20, cmap='RdBu_r', alpha=0.7)
plt.colorbar(contour, ax=ax, label='$\\nabla \\cdot \\mathbf{F}$')

ax.quiver(X[::skip, ::skip], Y[::skip, ::skip],
          Fx[::skip, ::skip], Fy[::skip, ::skip],
          color='black', scale=80, width=0.003)
ax.set_title('$\\mathbf{F} = (x^2, xy)$: $\\nabla \\cdot \\mathbf{F} = 3x$')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')

plt.tight_layout()
plt.savefig("divergence_examples.png", dpi=150, bbox_inches='tight')
plt.show()

ガウスの発散定理の数値検証

import numpy as np
import matplotlib.pyplot as plt

# ガウスの発散定理を数値的に検証する
# F = (x^2, y^2) について、正方形 [-1,1] x [-1,1] で検証

# 右辺: 体積分 ∫∫ div(F) dA
# div(F) = 2x + 2y
N = 1000
x = np.linspace(-1, 1, N)
y = np.linspace(-1, 1, N)
X, Y = np.meshgrid(x, y)
dx = x[1] - x[0]
dy = y[1] - y[0]

div_F = 2*X + 2*Y
volume_integral = np.sum(div_F) * dx * dy
print(f"体積分(右辺): {volume_integral:.6f}")

# 左辺: 面積分 ∮ F · n dS(4辺の寄与の合計)
# 右辺 (x=1): F·n = (1, y^2)·(1, 0) = 1
right = np.sum(np.ones(N)) * dy

# 左辺 (x=-1): F·n = (1, y^2)·(-1, 0) = -1
left = np.sum(-np.ones(N)) * dy

# 上辺 (y=1): F·n = (x^2, 1)·(0, 1) = 1
top = np.sum(np.ones(N)) * dx

# 下辺 (y=-1): F·n = (x^2, 1)·(0, -1) = -1
bottom = np.sum(-np.ones(N)) * dx

surface_integral = right + left + top + bottom
print(f"面積分(左辺): {surface_integral:.6f}")
print(f"一致: {np.isclose(volume_integral, surface_integral, atol=0.01)}")

# 解析解の確認
# ∫_{-1}^{1}∫_{-1}^{1} (2x + 2y) dx dy = 0(奇関数の積分)
print(f"解析解: 0.0000")

湧き出しと吸い込みのアニメーション的な表示

import numpy as np
import matplotlib.pyplot as plt

# 湧き出し・吸い込みの直感的な可視化
fig, axes = plt.subplots(1, 3, figsize=(15, 4.5))

x = np.linspace(-2, 2, 200)
y = np.linspace(-2, 2, 200)
X, Y = np.meshgrid(x, y)

# --- 湧き出し(Source)---
ax = axes[0]
R = np.sqrt(X**2 + Y**2) + 0.1
Fx = X / R
Fy = Y / R
ax.streamplot(X, Y, Fx, Fy, color='blue', density=1.5, linewidth=1.5, arrowsize=1.5)
circle = plt.Circle((0, 0), 0.15, color='red', zorder=5)
ax.add_patch(circle)
ax.set_title('Source: $\\nabla \\cdot \\mathbf{F} > 0$\n(Fluid flows outward)')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)

# --- 吸い込み(Sink)---
ax = axes[1]
Fx = -X / R
Fy = -Y / R
ax.streamplot(X, Y, Fx, Fy, color='green', density=1.5, linewidth=1.5, arrowsize=1.5)
circle = plt.Circle((0, 0), 0.15, color='purple', zorder=5)
ax.add_patch(circle)
ax.set_title('Sink: $\\nabla \\cdot \\mathbf{F} < 0$\n(Fluid flows inward)')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)

# --- ソレノイダル場(div = 0)---
ax = axes[2]
Fx = -Y
Fy = X
ax.streamplot(X, Y, Fx, Fy, color='orange', density=1.5, linewidth=1.5, arrowsize=1.5)
ax.set_title('Solenoidal: $\\nabla \\cdot \\mathbf{F} = 0$\n(No source/sink)')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)

plt.tight_layout()
plt.savefig("divergence_intuition.png", dpi=150, bbox_inches='tight')
plt.show()

まとめ

本記事では、発散(div)の定義と物理的意味を解説しました。

  • 発散 $\nabla \cdot \bm{F}$ は、各点での 正味の湧き出し量(単位体積あたり) を表すスカラー場である
  • $\nabla \cdot \bm{F} > 0$ は湧き出し(source)、$< 0$ は吸い込み(sink)、$= 0$ はソレノイダル場を意味する
  • ガウスの発散定理: 閉曲面を通る流束 = 内部の発散の体積分
  • 物理では連続の式(質量保存)やガウスの法則(電磁気学)に現れる
  • 非圧縮性流体では $\nabla \cdot \bm{v} = 0$ が成り立つ

次のステップとして、以下の記事も参考にしてください。