物理学や工学では、空間の各点に何らかの量が割り当てられた状況を「場」(field)と呼びます。部屋の各点に温度が定まっていれば 温度場、空気の各点に速度が定まっていれば 速度場 です。前者のように各点にスカラー値が対応する場を スカラー場、後者のようにベクトル値が対応する場を ベクトル場 と呼びます。
スカラー場とベクトル場は、ベクトル解析の出発点です。ここから勾配(grad)、発散(div)、回転(curl)といった微分演算子が定義され、マクスウェル方程式やナビエ・ストークス方程式といった物理法則を記述する言語が整備されます。
本記事の内容
- 場(field)の概念
- スカラー場の定義と具体例
- ベクトル場の定義と具体例
- 等値面(等高線)と流線
- Pythonでのスカラー場・ベクトル場の可視化
前提知識
この記事を読む前に、以下の知識があると理解が深まります。
- 多変数関数の基本($f(x, y)$ や $f(x, y, z)$ の概念)
- ベクトルの基本演算(加法、スカラー倍)
場(field)とは
直感的な理解
「場」とは、空間の各点に何らかの量を対応させる規則 のことです。日常的な例で考えてみましょう。
- 天気図: 地図上の各地点に気温(スカラー)が対応 → スカラー場
- 天気図の風向き: 各地点に風速(ベクトル)が対応 → ベクトル場
- 地形図: 各地点に標高(スカラー)が対応 → スカラー場
- 川の流れ: 各地点に水の流速(ベクトル)が対応 → ベクトル場
数学的には、場とは空間上で定義された関数(写像)のことです。
スカラー場の定義
数学的定義
$D \subseteq \mathbb{R}^n$ を定義域とするとき、各点 $\bm{r} \in D$ に実数値 $f(\bm{r}) \in \mathbb{R}$ を対応させる関数
$$ \begin{equation} f: D \to \mathbb{R} \end{equation} $$
を スカラー場(scalar field)と呼びます。
3次元の場合は:
$$ f: \mathbb{R}^3 \to \mathbb{R}, \quad f(x, y, z) \in \mathbb{R} $$
2次元の場合は:
$$ f: \mathbb{R}^2 \to \mathbb{R}, \quad f(x, y) \in \mathbb{R} $$
物理的な例
| スカラー場 | 記号 | 単位 | 説明 |
|---|---|---|---|
| 温度場 | $T(x, y, z)$ | K | 空間の各点での温度 |
| 圧力場 | $p(x, y, z)$ | Pa | 流体の各点での圧力 |
| 電位(電圧) | $\phi(x, y, z)$ | V | 電場によるポテンシャル |
| 密度場 | $\rho(x, y, z)$ | kg/m³ | 物質の密度分布 |
| 重力ポテンシャル | $U(x, y, z)$ | J/kg | 重力場のポテンシャルエネルギー |
等値面と等高線
スカラー場 $f(x, y, z)$ において、$f$ の値が一定値 $c$ となる点の集合:
$$ \begin{equation} S_c = \{(x, y, z) \mid f(x, y, z) = c\} \end{equation} $$
を 等値面(level surface)と呼びます。2次元スカラー場 $f(x, y)$ の場合は 等高線(contour line)と呼びます。
等高線は地形図でおなじみの概念です。等高線が密集している場所は傾斜が急で、間隔が広い場所は緩やかです。この「傾斜の急さと方向」を数学的に捉えるのが、次の記事で扱う 勾配(gradient)です。
ベクトル場の定義
数学的定義
$D \subseteq \mathbb{R}^n$ を定義域とするとき、各点 $\bm{r} \in D$ にベクトル $\bm{F}(\bm{r}) \in \mathbb{R}^n$ を対応させる関数
$$ \begin{equation} \bm{F}: D \to \mathbb{R}^n \end{equation} $$
を ベクトル場(vector field)と呼びます。
3次元の場合、ベクトル場は3つの成分関数で表されます:
$$ \bm{F}(x, y, z) = F_x(x,y,z)\bm{e}_x + F_y(x,y,z)\bm{e}_y + F_z(x,y,z)\bm{e}_z $$
あるいは成分表示で:
$$ \bm{F}(x, y, z) = (F_x(x,y,z), \; F_y(x,y,z), \; F_z(x,y,z)) $$
物理的な例
| ベクトル場 | 記号 | 説明 |
|---|---|---|
| 速度場 | $\bm{v}(x, y, z)$ | 流体の各点での速度 |
| 電場 | $\bm{E}(x, y, z)$ | 電荷が受ける力の方向と大きさ |
| 磁場 | $\bm{B}(x, y, z)$ | 磁気的な力の方向と大きさ |
| 重力場 | $\bm{g}(x, y, z)$ | 重力の方向と大きさ |
| 力場 | $\bm{F}(x, y, z)$ | 各点で質点に作用する力 |
流線
ベクトル場 $\bm{F}$ の 流線(streamline)とは、各点でベクトル場に接する曲線です。流線は媒介変数 $t$ を用いて、次の常微分方程式の解として定義されます。
$$ \begin{equation} \frac{d\bm{r}}{dt} = \bm{F}(\bm{r}(t)) \end{equation} $$
成分で書くと:
$$ \frac{dx}{dt} = F_x(x, y, z), \quad \frac{dy}{dt} = F_y(x, y, z), \quad \frac{dz}{dt} = F_z(x, y, z) $$
流体力学では、流線は流体粒子がたどる軌跡を表します(定常流の場合)。
スカラー場とベクトル場の関係
スカラー場とベクトル場は独立した概念ではなく、微分演算子で結ばれています。
- スカラー場に 勾配(grad)を作用させると ベクトル場 が得られる
- ベクトル場に 発散(div)を作用させると スカラー場 が得られる
- ベクトル場に 回転(curl)を作用させると ベクトル場 が得られる
$$ \text{スカラー場 } f \xrightarrow{\nabla} \text{ベクトル場 } \nabla f \xrightarrow{\nabla \cdot} \text{スカラー場 } \nabla^2 f $$
これらの演算子については、後続の記事で詳しく解説します。
Pythonでの実装
スカラー場の可視化(等高線)
import numpy as np
import matplotlib.pyplot as plt
# 2次元スカラー場: f(x, y) = x^2 + y^2(放物面 = 距離の2乗)
x = np.linspace(-3, 3, 200)
y = np.linspace(-3, 3, 200)
X, Y = np.meshgrid(x, y)
# スカラー場の定義
F = X**2 + Y**2
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
# 等高線プロット
ax = axes[0]
contour = ax.contourf(X, Y, F, levels=20, cmap='viridis')
ax.contour(X, Y, F, levels=20, colors='white', linewidths=0.3)
plt.colorbar(contour, ax=ax, label='$f(x, y)$')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_title('Scalar Field: $f(x, y) = x^2 + y^2$\n(Contour plot)')
ax.set_aspect('equal')
# 3Dサーフェスプロット
ax = fig.add_subplot(122, projection='3d')
# axes[1]を削除してから3Dに差し替え
axes[1].remove()
ax = fig.add_subplot(122, projection='3d')
ax.plot_surface(X, Y, F, cmap='viridis', alpha=0.8, edgecolor='none')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_zlabel('$f(x, y)$')
ax.set_title('$f(x, y) = x^2 + y^2$\n(Surface plot)')
plt.tight_layout()
plt.savefig("scalar_field.png", dpi=150, bbox_inches='tight')
plt.show()
温度場の可視化
import numpy as np
import matplotlib.pyplot as plt
# 2つの熱源による温度場
x = np.linspace(-5, 5, 300)
y = np.linspace(-5, 5, 300)
X, Y = np.meshgrid(x, y)
# 熱源1: (1, 1) に強度 Q1
# 熱源2: (-2, -1) に強度 Q2
def temperature_field(X, Y, sources):
"""複数の点熱源による温度場"""
T = np.zeros_like(X)
for (x0, y0, Q) in sources:
r = np.sqrt((X - x0)**2 + (Y - y0)**2 + 0.1) # 0.1は特異性を避けるため
T += Q / r
return T
sources = [(1, 1, 5), (-2, -1, 3)]
T = temperature_field(X, Y, sources)
fig, ax = plt.subplots(1, 1, figsize=(8, 6))
contour = ax.contourf(X, Y, T, levels=30, cmap='hot')
ax.contour(X, Y, T, levels=15, colors='white', linewidths=0.3, alpha=0.5)
plt.colorbar(contour, ax=ax, label='Temperature $T(x, y)$')
# 熱源の位置をプロット
for (x0, y0, Q) in sources:
ax.plot(x0, y0, 'c*', markersize=15, markeredgecolor='white', markeredgewidth=1)
ax.annotate(f'Source (Q={Q})', (x0, y0), textcoords="offset points",
xytext=(10, 10), color='white', fontsize=10)
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_title('Temperature Field with Two Heat Sources')
ax.set_aspect('equal')
plt.tight_layout()
plt.savefig("temperature_field.png", dpi=150, bbox_inches='tight')
plt.show()
ベクトル場の可視化
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# --- 例1: 一様場 F = (1, 0) ---
ax = axes[0, 0]
x = np.linspace(-2, 2, 10)
y = np.linspace(-2, 2, 10)
X, Y = np.meshgrid(x, y)
U = np.ones_like(X)
V = np.zeros_like(Y)
ax.quiver(X, Y, U, V, color='blue')
ax.set_title('Uniform Field: $\\mathbf{F} = (1, 0)$')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
# --- 例2: 放射状場 F = (x, y) ---
ax = axes[0, 1]
x = np.linspace(-2, 2, 12)
y = np.linspace(-2, 2, 12)
X, Y = np.meshgrid(x, y)
U = X
V = Y
magnitude = np.sqrt(U**2 + V**2)
ax.quiver(X, Y, U, V, magnitude, cmap='Reds')
ax.set_title('Radial Field: $\\mathbf{F} = (x, y)$')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
# --- 例3: 回転場 F = (-y, x) ---
ax = axes[1, 0]
U = -Y
V = X
magnitude = np.sqrt(U**2 + V**2)
ax.quiver(X, Y, U, V, magnitude, cmap='Blues')
ax.set_title('Rotational Field: $\\mathbf{F} = (-y, x)$')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
# --- 例4: 渦場(ランキン渦)---
ax = axes[1, 1]
x = np.linspace(-2, 2, 15)
y = np.linspace(-2, 2, 15)
X, Y = np.meshgrid(x, y)
R = np.sqrt(X**2 + Y**2) + 0.01
U = -Y / R**2
V = X / R**2
magnitude = np.sqrt(U**2 + V**2)
# 大きすぎるベクトルをクリップ
max_mag = 2
mask = magnitude > max_mag
U_clip = np.where(mask, U / magnitude * max_mag, U)
V_clip = np.where(mask, V / magnitude * max_mag, V)
ax.quiver(X, Y, U_clip, V_clip, np.minimum(magnitude, max_mag), cmap='Purples')
ax.set_title('Vortex Field: $\\mathbf{F} = \\frac{(-y, x)}{r^2}$')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("vector_fields.png", dpi=150, bbox_inches='tight')
plt.show()
流線の可視化
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
x = np.linspace(-3, 3, 200)
y = np.linspace(-3, 3, 200)
X, Y = np.meshgrid(x, y)
# --- 放射状場の流線 ---
ax = axes[0]
U = X
V = Y
ax.streamplot(X, Y, U, V, color=np.sqrt(U**2 + V**2), cmap='Reds',
density=1.5, linewidth=1.5, arrowsize=1.5)
ax.set_title('Streamlines: $\\mathbf{F} = (x, y)$\n(Source at origin)')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.set_xlim(-3, 3)
ax.set_ylim(-3, 3)
# --- 回転場の流線 ---
ax = axes[1]
U = -Y
V = X
ax.streamplot(X, Y, U, V, color=np.sqrt(U**2 + V**2), cmap='Blues',
density=1.5, linewidth=1.5, arrowsize=1.5)
ax.set_title('Streamlines: $\\mathbf{F} = (-y, x)$\n(Rotation around origin)')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_aspect('equal')
ax.set_xlim(-3, 3)
ax.set_ylim(-3, 3)
plt.tight_layout()
plt.savefig("streamlines.png", dpi=150, bbox_inches='tight')
plt.show()
まとめ
本記事では、スカラー場とベクトル場の定義と直感的な意味を解説しました。
- スカラー場 は空間の各点にスカラー値を対応させる関数で、温度場や圧力場が典型例である
- ベクトル場 は空間の各点にベクトル値を対応させる関数で、速度場や電場が典型例である
- スカラー場は 等高線(等値面)で可視化でき、等高線の密度が値の変化の急さを表す
- ベクトル場は 矢印プロット や 流線 で可視化できる
- スカラー場とベクトル場は、勾配・発散・回転といった 微分演算子 で結ばれている
次のステップとして、以下の記事も参考にしてください。