텐서 표기와 좌표계

3~12장에서 나비에-스토크스를 한 줄로 쓰기 위해 필요한 표기법 — 인덱스 표기, 아인슈타인 합 규약, 그리고 직교좌표 한정의 약속.

들어가며

이 장은 새로운 물리를 다루지 않는다. 대신 3장부터 모든 방정식을 한 줄로 줄여 쓰기 위한 도구를 정비한다. 학습 목표는 단순하다 — uiu_i를 보고 “벡터 u\vec{u}ii번째 성분”이라 즉시 읽을 수 있게 되는 것, 그리고 같은 인덱스가 두 번 나오면 “\sum이 생략됐다”라고 자동 해석할 수 있게 되는 것이다.

본론 1 — 벡터를 성분으로 쪼개기

3차원 직교좌표계(Cartesian coordinate system, 데카르트 좌표계)에서 속도 벡터는 세 개의 성분을 가진다:

u=(ux,uy,uz)=(u1,u2,u3)\vec{u} = (u_x, u_y, u_z) = (u_1, u_2, u_3)

여기서 첨자 1, 2, 3은 각각 x,y,zx, y, z축에 대응한다. 즉 u1uxu_1 \equiv u_x, u2uyu_2 \equiv u_y, u3uzu_3 \equiv u_z이다. 좌표축 자체도 같은 방식으로 (x1,x2,x3)(x_1, x_2, x_3)로 쓴다.

이 표기의 이점은 일반화된 인덱스 ii를 한 번 도입하면 세 성분에 대한 진술을 한 줄로 압축할 수 있다는 점이다:

ui,i{1,2,3}u_i, \quad i \in \{1, 2, 3\}

이 한 줄은 ”u1,u2,u3u_1, u_2, u_3 모두에 대해 다음이 성립한다”라는 뜻을 함축한다. 자유 인덱스(free index) ii는 식 양변에 같이 나타나며, “성분별로 하나씩 식이 세 개 있다”라는 의미가 된다.

본론 2 — 아인슈타인 합 규약

두 벡터 a,b\vec{a}, \vec{b}의 내적(dot product)을 인덱스 표기로 쓰면:

ab=i=13aibi=a1b1+a2b2+a3b3\vec{a} \cdot \vec{b} = \sum_{i=1}^{3} a_i b_i = a_1 b_1 + a_2 b_2 + a_3 b_3

여기서 인덱스 ii가 한 항 안에서 두 번 반복된다. 아인슈타인(Einstein, 아인슈타인)이 1916년 일반상대성이론 논문에서 도입한 규약은 단순하다 — 같은 항에서 반복되는 인덱스는 1부터 3까지 자동으로 합한다고 약속하고, \sum 기호를 생략한다:

aibii=13aibi=a1b1+a2b2+a3b3a_i b_i \equiv \sum_{i=1}^{3} a_i b_i = a_1 b_1 + a_2 b_2 + a_3 b_3

반복된 인덱스를 더미 인덱스(dummy index)라 부른다. 더미 인덱스는 이름을 바꿔도 식의 의미가 변하지 않는다. 즉 aibi=ajbj=akbka_i b_i = a_j b_j = a_k b_k이다. 마치 i=13f(i)\sum_{i=1}^{3} f(i)j=13f(j)\sum_{j=1}^{3} f(j)가 같은 수인 것과 같다.

한 항에 같은 인덱스가 세 번 이상 나오면 표기 오류다. 또한 양변의 자유 인덱스는 정확히 일치해야 한다 — 좌변에 ii가 자유롭게 남아 있으면 우변에도 ii가 자유롭게 남아 있어야 한다.

본론 3 — 랭크 2 텐서와 응력

스칼라는 방향이 없는 양(온도 등), 벡터는 방향이 하나인 양(속도 등)이다. 랭크 2 텐서(rank-2 tensor)는 방향이 두 개인 양이다. 가장 대표적인 예가 응력 텐서(stress tensor) σij\sigma_{ij}이다.

σij\sigma_{ij}는 ”jj 방향 면의 단위 면적에 작용하는 힘의 ii 방향 성분”을 뜻한다. 두 개의 자유 인덱스 i,ji, j가 각각 1, 2, 3을 돌므로 응력 텐서는 총 3×3=93 \times 3 = 9개의 성분을 가진다:

σij=(σ11σ12σ13σ21σ22σ23σ31σ32σ33)\sigma_{ij} = \begin{pmatrix} \sigma_{11} & \sigma_{12} & \sigma_{13} \\ \sigma_{21} & \sigma_{22} & \sigma_{23} \\ \sigma_{31} & \sigma_{32} & \sigma_{33} \end{pmatrix}

3장에서 등장할 속도 기울기(velocity gradient) ui/xj\partial u_i / \partial x_j도 같은 구조다 — ii는 어느 속도 성분인지, jj는 어느 방향으로 미분하는지를 가리키며 총 9개의 편미분을 한 기호로 묶는다. 이런 압축이 없으면 나비에-스토크스 방정식은 한 페이지가 된다.

본론 4 — 이 책에서는 직교좌표만 쓴다

일반적인 텐서 해석에서는 곡선좌표계(원통, 구면 등)도 다루며, 이때는 크리스토펠 기호(Christoffel symbol, 크리스토펠), 공변(covariant)과 반변(contravariant)의 구분이 등장한다. 이 책은 모든 장에서 3차원 직교좌표계만 사용한다. 따라서:

  • 인덱스를 위첨자/아래첨자로 구분할 필요가 없다 (모두 아래첨자로 쓴다).
  • 크리스토펠 기호는 0이므로 무시한다.
  • 좌표축은 직선이고 단위 벡터는 위치에 무관하게 일정하다.

이 약속 덕분에 표기가 훨씬 간단해진다. 곡선좌표계가 필요한 응용(원통 파이프, 회전기계 내부 흐름 등)에서는 보통 결과식만 좌표 변환으로 옮기고, 유도 자체는 직교좌표에서 한다.

파이썬으로 확인

내적을 손으로 적은 세 곱의 합으로 계산하는 방법과, numpy의 einsum으로 계산하는 방법이 같은 값을 주는지 확인해 보자. einsum('i,i->', a, b)라는 표기는 “인덱스 ii가 두 번 반복되니 합하라, 결과는 스칼라”라는 아인슈타인 규약을 그대로 코드로 옮긴 것이다.

import numpy as np

# 임의의 두 3차원 벡터 (재현성을 위해 시드 고정)
rng = np.random.default_rng(0)
a = rng.standard_normal(3)
b = rng.standard_normal(3)

# 방법 1 — 손으로 적은 세 곱의 합
manual = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]

# 방법 2 — 아인슈타인 합 규약 (반복된 i를 자동으로 합)
einstein = np.einsum('i,i->', a, b)

# 참고용 — np.dot도 같은 결과
dot = np.dot(a, b)

print(f"a = {a}")
print(f"b = {b}")
print(f"수동 계산  : {manual:.6f}")
print(f"einsum    : {einstein:.6f}")
print(f"np.dot    : {dot:.6f}")
print(f"세 값이 같은가? {np.allclose([manual, einstein, dot], manual)}")

einsum의 문법 'i,i->'은 그대로 수식이다 — 콤마 앞뒤가 두 입력 텐서의 인덱스, 화살표 뒤가 출력 인덱스다. 출력에 인덱스가 비어 있으면 “스칼라”라는 뜻이고, 입력에서 반복된 ii는 합산된다. 다시 말해 아인슈타인 표기는 numpy가 이미 하던 일에 이름을 붙인 것일 뿐이다.

다음 장으로

이제 표기 도구가 갖춰졌다. 3장: 나비에-스토크스 방정식 복습에서는 이 표기를 써서 질량보존과 운동량보존을 각각 한 줄로 쓴다. 만약 본문 중간에 ui/xi\partial u_i / \partial x_i 같은 식이 어색하게 느껴진다면, 이 장으로 돌아와 “반복된 ii는 합”이라는 규칙을 다시 확인하면 된다.