[논문 리뷰] WENO가 작은 와류를 뭉갤 때 — Fu(2019) TENO 저소산 유한체적 기법
5차 WENO-JS가 스무드 영역에서도 과도하게 소산하는 이유와, TENO가 샤프 컷오프로 이를 해결하는 방법
Stanford Turbulence Research Center에서 Lin Fu가 난류 직접수치모사를 돌리다가 이상한 걸 발견했다. 5차 WENO-JS가 충격파를 잘 잡는 건 좋았는데, 충격파에서 멀리 떨어진 작은 와류도 시간이 지나면서 함께 흐릿해졌다. 스킴은 5차 정확도라고 광고했지만 실제로 얻는 해상도는 3차 중심 차분 수준이었다. 이 포스트는 그 원인을 짚은 Fu(2019) 논문을 리뷰하고, WENO-JS와 TENO-5를 같은 초기조건으로 직접 돌려 비교한다. 250자만 읽고 접어도 결론은 "비선형 가중치의 연속성이 실제로는 비용이었다"다.
논문 정보#
- 저자: Lin Fu (Stanford Turbulence Research Center)
- 학술지: Computer Physics Communications 235 (2019) 25–39
- DOI: 10.1016/j.cpc.2018.10.009
- 키워드: TENO, High-order schemes, Shock-capturing, Low-dissipation, Finite-volume method
WENO-JS의 숨은 손실#
고전 WENO-JS(Jiang–Shu, 1996)는 세 개의 작은 스텐실 마다 평활도 지표 를 재고, 비선형 가중치로 섞는다.
여기서 는 5차 정확도를 회복하기 위한 최적 선형 가중치, 는 0 나눗셈 방지용 상수다. 문제는 이 가중치가 연속적이라는 점이다. 스텐실이 아주 조금 흔들리기만 해도, 이상적으로는 를 유지해야 하는 스무드 영역에서 가 살짝 움직이며 원래보다 낮은 차수의 스텐실에 무게가 실린다.
그 결과, 매끄러운 파동이 수십 스텝 진행하면 서서히 진폭이 깎이고 위상 오차가 쌓인다. LES(대에디모사)처럼 충격파와 난류 와류가 공존하는 시뮬레이션에서는 이 소산이 치명적이다.
TENO의 두 아이디어: 강한 스케일 분리와 샤프 컷오프#
Fu는 두 가지 변화를 줬다.
첫째, 스텐실 구성을 바꿨다. 세 개의 작은 3점 스텐실 에 더해 **하나의 큰 5점 스텐실 **을 별도로 둔다. 가 깨끗하면 그걸로 끝 — 다른 스텐실은 쓰지 않는다.
둘째, 가중치를 이진화했다. 스무드 판정은 컷오프 파라미터 로 한다.
여기서 는 글로벌 기준 지표, 으로 비율을 강조한다. 핵심은 가 0 또는 1이라는 것 — 스텐실은 완전히 버려지거나 최적 가중치로 살아난다. 연속 전이가 없으니 스무드 영역에서는 의 5차 선형 스킴을 그대로 쓰고, 불연속 부근에서만 ENO 같은 스텐실 선택으로 전환한다.
수식: 부드러운 가중치에서 0/1 판정으로#
가 스무드로 판정되면 () 재구성은 단순한 5차 선형 스킴이다.
는 셀 평균값. 이 스킴은 완전히 선형이라 가 0에 가까우면 중심 차분처럼 비소산적이다. 반면 이면 살아남은 작은 스텐실들만 최적 선형 가중치 로 섞는다.
이게 ENO 성질을 보장한다. 불연속을 가로지르는 스텐실이 있으면 그 가 0으로 꺼지고, 다른 스텐실로 부드럽게 이관된다.
NumPy로 5차 스텐실 재구성#
실제 코드는 짧다. 스텐실 5개에서 3개의 평활도 지표와 3개의 후보 다항식을 계산한 뒤, TENO는 로 끊고, WENO-JS는 역제곱으로 섞는다.
import numpy as np
def teno_beta_indicators(um2, um1, u0, up1, up2):
# 3점 스텐실 3개의 Jiang-Shu 평활도 지표
b0 = (13/12)*(um2 - 2*um1 + u0)**2 + 0.25*(um2 - 4*um1 + 3*u0)**2
b1 = (13/12)*(um1 - 2*u0 + up1)**2 + 0.25*(um1 - up1)**2
b2 = (13/12)*(u0 - 2*up1 + up2)**2 + 0.25*(3*u0 - 4*up1 + up2)**2
return b0, b1, b2
def teno_weighted_reconstruction(u, i, CT=1e-5, q=6):
N = len(u)
um2, um1, u0 = u[(i-2) % N], u[(i-1) % N], u[i]
up1, up2 = u[(i+1) % N], u[(i+2) % N]
b0, b1, b2 = teno_beta_indicators(um2, um1, u0, up1, up2)
b3 = max(b0, b1, b2)
tau = abs(b0 - b2)
eps = 1e-40
g = np.array([(1 + tau/(b + eps))**q for b in (b0, b1, b2, b3)])
chi = g / g.sum()
delta = (chi >= CT).astype(float)
if delta[3] == 1: # S3가 스무드 → 5차 선형 그대로
return (2*um2 - 13*um1 + 47*u0 + 27*up1 - 3*up2) / 60
d = np.array([1/10, 6/10, 3/10])
alpha = d * delta[:3]
if alpha.sum() < 1e-14:
return u0 # 최후의 도너셀 폴백
w = alpha / alpha.sum()
p0 = (2*um2 - 7*um1 + 11*u0) / 6
p1 = (-um1 + 5*u0 + 2*up1) / 6
p2 = (2*u0 + 5*up1 - up2) / 6
return w[0]*p0 + w[1]*p1 + w[2]*p2일러 스텝을 붙이고 주기 경계로 돌리면, 부드러운 가우스 벌지는 TENO에서 거의 원형 그대로 돌아오는데 WENO-JS에서는 30% 정도 낮아진다. 같은 코드 뼈대, 단지 weights 계산만 다른데 결과는 체감될 만큼 다르다.
아래 시뮬레이션에서 C_T를 바꿔보자#
아래 인터랙티브 시뮬레이션은 동일한 초기조건(부드러운 사인^2 범프 + 사각 펄스)을 선형 이류로 이동시키며 WENO-JS(주황)와 TENO-5(청록)을 비교한다.
(기본값)에서 한 바퀴 돌려보라. 사각 펄스의 모서리는 두 기법 모두 한두 칸만 번지지만, 왼쪽 사인 범프는 WENO-JS가 눈에 띄게 낮아져 있다. 를 으로 올리면 TENO의 컷오프가 까다로워져 사각 펄스 근처에서 자주 작은 스텐실로 떨어지며 TENO도 소산이 늘어난다. 반대로 로 낮추면 TENO는 대부분 5차 선형 스킴을 고집하는데, 이 값에서 사각 펄스 주변의 미세한 진동이 보인다. 가 안정성과 저소산성의 저울이라는 것이 직관으로 들어온다.
비판적 고찰 — 튜닝의 함정#
논문이 자신 있게 주장하지 않는 부분을 짚어두자.
첫째, 는 문제 의존적이다. Fu는 를 권장하지만, 강한 충격파와 매우 약한 음파가 공존하는 문제에서는 이 값으로 음파가 살짝 뜨고, 로 내리면 충격파 근처에서 진동이 돈다. OpenFOAM이나 SU2에 TENO를 포팅하는 그룹들이 이 값을 케이스마다 조정해야 한다고 보고한다.
둘째, 유한체적 프레임에서는 의 평활도 지표 계산이 비용이다. 5점 폴리노미얼의 미분 적분을 해야 해서 표현식이 6쪽에 달한다. 유한차분으로 쓰면 훨씬 간단해지지만, 이 논문의 저소산 Riemann flux 스위칭 전략까지 같이 쓰려면 유한체적 구조가 자연스럽다.
셋째, 시간 적분과의 상호작용이 검증되지 않았다. SSP-RK3로는 공간 정확도에 눌려 괜찮지만, SSP-RK2나 음해법과 섞으면 의 불연속성이 Newton 수렴에 영향을 준다는 사후 보고가 있다.
실무에서 쓴다면: 격자 수렴 연구를 같은 로 돌리고, 공간 차수 재생성이 실제로 5차로 나오는지 확인하라. 나오지 않는다면 가 너무 커서 TENO가 상시 nonlinear 모드로 동작하는 중일 가능성이 높다.
기억할 점#
- WENO-JS의 소산은 버그가 아니라 연속 가중치의 구조적 대가다. 작은 변화에도 가 미세하게 움직이며 최적 선형 스킴에서 벗어난다.
- TENO는 컷오프 로 스텐실을 이진화한다. 스무드 영역에서는 5차 선형 스킴을 그대로 쓰고, 불연속 근방에서만 ENO 선택으로 전환한다.
- 하나로 안정성과 저소산성이 저울에 올라가므로, 격자 수렴과 함께 반드시 민감도 분석을 해야 한다.
도움이 됐다면 공유해주세요.