Traducción del original en coreano escrito por el autor. Leer el original (한국어)
[Reseña de artículo] GMRES corrió 1000 veces y no se detenía — precondicionamiento por bloques físico para un melt pool a toda velocidad
Los autovalores valen 1 solo con el complemento de Schur exacto. Una resolución floja de S por AMG vuelve a abrir el conteo externo.
Se corrió un melt pool láser en forma implícita. En el primer paso de tiempo, GMRES dio 1000 vueltas y el residuo se quedó en 1e-2. Al bajar el Mach a 1e-3, la velocidad del sonido pasa a ser 1000 veces la del flujo. El jacobiano enfermó en esa razón. Weston, Nourgaliev, Delplanque y Barker (2019) cortaron el estancamiento usando el complemento de Schur velocidad–presión como precondicionador. Estas notas pasan ese precondicionador a un toy de 2 campos y anotan dónde se pega el número de iteraciones al cambiar el Mach.
Al bajar el control de Mach, solo la onda acústica de la pista superior se acelera, a . El trazador convectivo de abajo se queda en .
En la onda acústica da 100 vueltas a la pista mientras el trazador avanza una muesca. En la razón es 1000:1. La misma brecha de la noche en que el residuo se pegó en 1e-2.
Dónde se sitúa este artículo#
- Autores: B. Weston, R. Nourgaliev, J.-P. Delplanque, A. T. Barker (LLNL / UC Davis)
- Revista: Journal of Computational Physics, 397, 108847 (2019)
- Título: Preconditioning a Newton-Krylov solver for all-speed melt pool flow physics
- En una línea: resolver las Navier–Stokes compresibles a toda velocidad (all-speed) con cambio de fase mediante JFNK totalmente implícito, y domar la rigidez de bajo Mach con un precondicionador de complemento de Schur por bloques en variables primitivas.
Los precondicionadores habituales — SOR por bloque de elemento, AMG monolítico, Gauss–Seidel por bloques — disparan todos el número de iteraciones cuando el paso de tiempo o el Mach llegan a un extremo. Lo que entrega el artículo es el complemento de Schur vP-vT. La forma en bloques del acoplamiento físico se copia en la matriz del precondicionador.
Por qué el jacobiano enferma cuando M tiende a cero#
"A toda velocidad" significa que un mismo código resuelve desde lo incompresible () hasta lo supersónico. El problema es el límite de bajo Mach. La razón entre la velocidad acústica y la del flujo se abre como . En , el sonido va 1000 veces más rápido que el fluido.
Al ir totalmente implícito, esas dos escalas se mezclan dentro de un único jacobiano. El bloque de acoplamiento presión–velocidad crece como y el número de condición de la matriz se dispara. Un solver de Krylov se arrastra sobre autovalores muy esparcidos.
Al colocar en los cuatro puntos del código, sale directo. da . da . da . da . Una entrada del bloque presión–velocidad crece un millón de veces. La malla es y el espaciado en los cuatro casos. El tamaño de la matriz sigue en . Solo cambia el espectro escalado por .
Un CFL acústico aplasta el paso según . Bajar de 1 a reduce el paso admisible a la milésima parte. Lo totalmente implícito suelta ese límite y entrega el número de condición a . La misma rigidez, amplificada al revés por un precondicionador, está en el precondicionador por bloques con CFL acústico 10.
JFNK (Jacobian-Free Newton–Krylov) nunca forma el jacobiano de forma explícita; solo aproxima el producto matriz–vector con una diferencia de Fréchet.
es el residuo no lineal, un vector de Krylov y un número finito pequeño. No guardar la matriz reduce memoria. Sin precondicionador, esa diferencia camina los autovalores esparcidos en bajo Mach.
Soltar las variables conservativas por las primitivas #
El primer movimiento es un cambio de variables. En vez del conjunto conservativo , se resuelve por las primitivas , porque están mucho mejor condicionadas a bajo Mach.
es el jacobiano del cambio de variables. El residuo se sigue escribiendo para satisfacer las leyes de conservación, así que cambiar de variables no rompe la conservación de masa, momento ni energía. Ahora se ordenan los grados de libertad por campo en una matriz por bloques .
Cada bloque corresponde a un campo primitivo (velocidad, presión, temperatura). Ese orden es el trampolín de la factorización.
LU por bloques y el complemento de Schur velocidad–presión#
El acoplamiento presión–temperatura () es débil. Al descartar ambos, la factorización LU por bloques sale limpia y lo que queda es el complemento de Schur velocidad–presión.
es la ecuación efectiva para la presión tras eliminar la velocidad — el mismo esqueleto que la ecuación de corrección de presión de la familia SIMPLE. Toma el precondicionador con esta forma triangular superior por bloques y los autovalores de se agrupan cerca de 1. Con el exacto, el factor de es literalmente , de modo que es semejante a una triangular inferior unipotente: todos los autovalores valen exactamente 1. GMRES termina en dos o tres pasos.
El código para en rtol=1e-8, con tope maxiter=500 y reinicio 2n=128. Autovalores en un punto cierran el subespacio de Krylov en dos pasos. Si no, la corrida toca 500 antes.
Python — contar iteraciones de GMRES al bajar el Mach#
La temperatura queda fuera. El corazón se reproduce en un toy de 2 campos . El sistema por bloques es con . El precondicionador es el complemento de Schur exacto .
import numpy as np
from scipy.sparse import diags, eye, bmat
from scipy.sparse.linalg import gmres, LinearOperator, splu
n = 64
dx = 1.0 / n
def fwd_diff():
# diferencia hacia adelante periodica (operador de gradiente de presion)
D = diags([-1.0, 1.0], [0, 1], shape=(n, n)).tolil()
D[-1, 0] = 1.0
return (D / dx).tocsr()
G = fwd_diff()
Dv = (-G.T).tocsr() # divergencia = -G^T -> Dv*G ~ laplaciano
def all_speed_system(M):
beta = 1.0 / M**2 # factor de rigidez de bajo Mach
A = bmat([[eye(n), beta * G], [Dv, eye(n)]]).tocsr()
return A, beta
def schur_preconditioner(beta):
# complemento de Schur velocidad-presion S = M_PP - M_Pv M_vv^{-1} M_vP = I - beta Dv G
S = (eye(n) - beta * (Dv @ G)).tocsc()
luS = splu(S)
def apply(r):
ru, rp = r[:n], r[n:]
zp = luS.solve(rp) # S z_p = r_p
zu = ru - beta * (G @ zp) # z_u = r_u - beta G z_p
return np.concatenate([zu, zp])
return LinearOperator((2 * n, 2 * n), matvec=apply)
def count_iters(M, use_prec):
A, beta = all_speed_system(M)
b = np.random.default_rng(0).standard_normal(2 * n)
P = schur_preconditioner(beta) if use_prec else None
it = {"k": 0}
x, info = gmres(A, b, M=P, rtol=1e-8, maxiter=500, restart=2 * n,
callback=lambda xk: it.__setitem__("k", it["k"] + 1))
return it["k"]
print(f"{'Mach':>8} {'no-prec':>8} {'Schur':>6}")
for M in [1.0, 1e-1, 1e-2, 1e-3]:
print(f"{M:>8.0e} {count_iters(M, False):>8d} {count_iters(M, True):>6d}")Sin precondicionador, el número de iteraciones trepa a decenas y cientos a medida que encoge, y en ni siquiera entra en el tope de 500. El lado de Schur factoriza una vez por LU, y GMRES baja el residuo a 1e-11 en dos o tres pasos. Conteos de Schur iguales en () y en () son la cara numérica de autovalores apilados en 1.
Interactivo — acústica y convección, dos velocidades que se separan#
La brecha 100:1 en es . El jacobiano recibe el cuadrado, . En , . En forma explícita, .
Interactivo — dónde el precondicionador derrumba el residuo#
Ahora el residuo real de GMRES. Al mover el control de Mach, las dos curvas — con y sin precondicionamiento — se redibujan.
La curva naranja (sin precondicionador) se aplana y se estanca al bajar . La curva cian (precondicionada con Schur) se desploma a 1e-11 en dos o tres pasos, esté donde esté . La brecha es máxima en . El bloque escalado por queda absorbido entero por un precondicionador copiado del acoplamiento físico.
Tres cosas que generaron dudas al programarlo#
Un exacto solo es gratis en un toy. Aquí se factorizó por LU y la convergencia llegó en dos pasos. En la práctica, el dentro de es una inversa densa que no se puede formar. El artículo resuelve de forma aproximada (un V-cycle de AMG, por ejemplo), y la calidad de esa aproximación gobierna el número de iteraciones externas. El costo de un conteo plano en Mach se esconde aquí.
Hasta dónde descartar el acoplamiento. El artículo dice que descartar no cuesta robustez. Es un supuesto ajustado a la física del melt pool. Con un acoplamiento térmico compresible fuerte — deflagración, combustión — el mismo truncamiento puede frenar la convergencia. Si el precondicionador se simplifica, lo decide la física.
La diferencia de Fréchet de JFNK. Un demasiado pequeño deja entrar el redondeo; demasiado grande deja que el error de truncamiento contamine el producto matriz–vector. Aun con un buen precondicionador, un mal ajustado estanca a Newton. Es el primer tropiezo al pasar del enfoque segregado (SIMPLE) de OpenFOAM a uno totalmente acoplado e implícito.
Cierre — un precondicionador no es gratis#
La noche en que GMRES se detuvo en 1000 iteraciones y un residuo de 1e-2 no se cerró apretando más el jacobiano. Hacía falta un precondicionador que copiara el propio acoplamiento. El complemento de Schur es la ecuación de presión con la velocidad eliminada, y resolverlo de forma exacta agrupa los autovalores en 1. En un real, es denso, así que el artículo lo aproxima con un V-cycle de AMG. Un ciclo áspero vuelve a abrir el conteo externo desde dos o tres pasos.
No guardar el jacobiano y quedarse solo con el producto matriz–vector es la misma bifurcación que la diferenciación automática por sobrecarga de operadores. JFNK sustituye ese producto por la diferencia de Fréchet . Un desviado detiene a Newton aunque el precondicionador esté bien. La medición siguiente, en el mismo toy, es cuánto se aleja el conteo externo de dos o tres pasos cuando se resuelve de forma floja con AMG.
Relacionados
Comparte si te resultó útil.