텐서 표기와 좌표계
텐서 표기와 좌표계
3~12장에서 나비에-스토크스를 한 줄로 쓰기 위해 필요한 표기법 — 인덱스 표기, 아인슈타인 합 규약, 그리고 직교좌표 한정의 약속.
들어가며
이 장은 새로운 물리를 다루지 않는다. 대신 3장부터 모든 방정식을 한 줄로 줄여 쓰기 위한 도구를 정비한다. 학습 목표는 단순하다 — 를 보고 “벡터 의 번째 성분”이라 즉시 읽을 수 있게 되는 것, 그리고 같은 인덱스가 두 번 나오면 “이 생략됐다”라고 자동 해석할 수 있게 되는 것이다.
본론 1 — 벡터를 성분으로 쪼개기
3차원 직교좌표계(Cartesian coordinate system, 데카르트 좌표계)에서 속도 벡터는 세 개의 성분을 가진다:
여기서 첨자 1, 2, 3은 각각 축에 대응한다. 즉 , , 이다. 좌표축 자체도 같은 방식으로 로 쓴다.
이 표기의 이점은 일반화된 인덱스 를 한 번 도입하면 세 성분에 대한 진술을 한 줄로 압축할 수 있다는 점이다:
이 한 줄은 ” 모두에 대해 다음이 성립한다”라는 뜻을 함축한다. 자유 인덱스(free index) 는 식 양변에 같이 나타나며, “성분별로 하나씩 식이 세 개 있다”라는 의미가 된다.
본론 2 — 아인슈타인 합 규약
두 벡터 의 내적(dot product)을 인덱스 표기로 쓰면:
여기서 인덱스 가 한 항 안에서 두 번 반복된다. 아인슈타인(Einstein, 아인슈타인)이 1916년 일반상대성이론 논문에서 도입한 규약은 단순하다 — 같은 항에서 반복되는 인덱스는 1부터 3까지 자동으로 합한다고 약속하고, 기호를 생략한다:
반복된 인덱스를 더미 인덱스(dummy index)라 부른다. 더미 인덱스는 이름을 바꿔도 식의 의미가 변하지 않는다. 즉 이다. 마치 와 가 같은 수인 것과 같다.
한 항에 같은 인덱스가 세 번 이상 나오면 표기 오류다. 또한 양변의 자유 인덱스는 정확히 일치해야 한다 — 좌변에 가 자유롭게 남아 있으면 우변에도 가 자유롭게 남아 있어야 한다.
본론 3 — 랭크 2 텐서와 응력
스칼라는 방향이 없는 양(온도 등), 벡터는 방향이 하나인 양(속도 등)이다. 랭크 2 텐서(rank-2 tensor)는 방향이 두 개인 양이다. 가장 대표적인 예가 응력 텐서(stress tensor) 이다.
는 ” 방향 면의 단위 면적에 작용하는 힘의 방향 성분”을 뜻한다. 두 개의 자유 인덱스 가 각각 1, 2, 3을 돌므로 응력 텐서는 총 개의 성분을 가진다:
3장에서 등장할 속도 기울기(velocity gradient) 도 같은 구조다 — 는 어느 속도 성분인지, 는 어느 방향으로 미분하는지를 가리키며 총 9개의 편미분을 한 기호로 묶는다. 이런 압축이 없으면 나비에-스토크스 방정식은 한 페이지가 된다.
본론 4 — 이 책에서는 직교좌표만 쓴다
일반적인 텐서 해석에서는 곡선좌표계(원통, 구면 등)도 다루며, 이때는 크리스토펠 기호(Christoffel symbol, 크리스토펠), 공변(covariant)과 반변(contravariant)의 구분이 등장한다. 이 책은 모든 장에서 3차원 직교좌표계만 사용한다. 따라서:
- 인덱스를 위첨자/아래첨자로 구분할 필요가 없다 (모두 아래첨자로 쓴다).
- 크리스토펠 기호는 0이므로 무시한다.
- 좌표축은 직선이고 단위 벡터는 위치에 무관하게 일정하다.
이 약속 덕분에 표기가 훨씬 간단해진다. 곡선좌표계가 필요한 응용(원통 파이프, 회전기계 내부 흐름 등)에서는 보통 결과식만 좌표 변환으로 옮기고, 유도 자체는 직교좌표에서 한다.
파이썬으로 확인
내적을 손으로 적은 세 곱의 합으로 계산하는 방법과, numpy의 einsum으로 계산하는 방법이 같은 값을 주는지 확인해 보자. einsum('i,i->', a, b)라는 표기는 “인덱스 가 두 번 반복되니 합하라, 결과는 스칼라”라는 아인슈타인 규약을 그대로 코드로 옮긴 것이다.
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->'은 그대로 수식이다 — 콤마 앞뒤가 두 입력 텐서의 인덱스, 화살표 뒤가 출력 인덱스다. 출력에 인덱스가 비어 있으면 “스칼라”라는 뜻이고, 입력에서 반복된 는 합산된다. 다시 말해 아인슈타인 표기는 numpy가 이미 하던 일에 이름을 붙인 것일 뿐이다.
다음 장으로
이제 표기 도구가 갖춰졌다. 3장: 나비에-스토크스 방정식 복습에서는 이 표기를 써서 질량보존과 운동량보존을 각각 한 줄로 쓴다. 만약 본문 중간에 같은 식이 어색하게 느껴진다면, 이 장으로 돌아와 “반복된 는 합”이라는 규칙을 다시 확인하면 된다.