スカラー場とベクトル場の定義を直感的に理解する

物理学や工学では、空間の各点に何らかの量が割り当てられた状況を「場」(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()

まとめ

本記事では、スカラー場とベクトル場の定義と直感的な意味を解説しました。

  • スカラー場 は空間の各点にスカラー値を対応させる関数で、温度場や圧力場が典型例である
  • ベクトル場 は空間の各点にベクトル値を対応させる関数で、速度場や電場が典型例である
  • スカラー場は 等高線(等値面)で可視化でき、等高線の密度が値の変化の急さを表す
  • ベクトル場は 矢印プロット流線 で可視化できる
  • スカラー場とベクトル場は、勾配・発散・回転といった 微分演算子 で結ばれている

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