Traducción del original en coreano escrito por el autor. Leer el original (한국어)
Cuando FTCS tiembla, el upwind se entumece — esquema advectivo de primer orden, viscosidad artificial y el trueque de CFL
Con 200 celdas y c=0.8, una vuelta son 250 pasos. El bucle de 400 pasos recorre 1.6 vueltas, así que el pulso ya no está sobre q0.
A comienzos de los años sesenta, gente junto a von Neumann metió diferencias centradas en la advección lineal unidimensional. El pulso cuadrado debía derivar en calma. El borde de salida creció en oscilaciones y salió de la malla en pocos pasos.
La causa no es el orden. Traer el valor de aguas abajo con el mismo peso rompe la causalidad. Un upwind de una celda frena esa huida y mata las esquinas. El límite de ese trueque es el número CFL.
Al mover la marca CFL de 0.05 a 1.5, sobre el mismo pulso cuadrado, FTCS sigue temblando y el upwind cae sobre la línea de trazos solo cerca de 1.
Con la marca en 0.5 el pulso upwind se abre más. Pasado 1.05, el upwind y Lax–Wendroff se van juntos del marco. El stencil quedó más corto que la característica.
La diferencia más natural cae primero#
La advección lineal en una dimensión es una sola línea.
es la cantidad transportada y una velocidad constante. La solución es la forma inicial trasladada a velocidad .
Euler hacia adelante en el tiempo y una diferencia centrada de segundo orden en el espacio dan esta actualización.
es el número de Courant, las celdas que la onda cruza en un paso. El esquema es de segundo orden en espacio y de primer orden en tiempo, así que el LTE (error local de truncamiento) es . Por más que se reduzca , el esquema se dispara.
Al sustituir , el factor de amplificación es
y . Todo modo crece en cada paso. Basta un modo con mayor que 1 para romper el campo.
Con el del código, el modo con mide . Es 1.28 por paso, y 400 pasos son esa potencia. El aproximado de más abajo no es este modo. La fórmula da 1.28.
La información solo fluye desde un lado#
Si , en solo puede mirar aguas arriba, en . La diferencia centrada toma el valor de aguas abajo con el mismo peso. Lee un lado al que el flujo no ha llegado.
El upwind fija esa dirección.
El factor de amplificación es
y . Para , .
El coeficiente llega a 0.25 en . En vale 0.16. En la onda más corta, , o sea . En el de ese modo cae a 0. En la resta desaparece y todo modo tiene . El emborronado máximo está en 0.5, no en el borde del intervalo estable.
Upwind = centrada + una viscosidad oculta#
Al partir la pendiente upwind de primer orden sale la identidad
El término de delante es la diferencia centrada. El de detrás es una segunda derivada discreta. Así, el upwind integra en realidad
El objetivo era la advección. El algoritmo metió una viscosidad . Viscosidad artificial, también llamada difusión numérica.
Esa viscosidad mata la huida. Las esquinas del pulso cuadrado se abren hasta un espesor . Un menor recorta la viscosidad, pero llegar al mismo tiempo pide más pasos, y el emborronado se queda.
El coeficiente posterior no coincide con esta fórmula por culpa de . El de arriba es el extremo . Con , , así que el coeficiente que queda es la quinta parte, . Solo la forma con se anula en .
CFL — cuando la malla no alcanza la característica#
El valor de en es el que estaba en en el tiempo . Si ese pie cae entre y , dos valores de malla lo interpolan. En cuanto , el pie queda más allá de . El stencil no mira hasta ahí.
Esa geometría es la condición de Courant–Friedrichs–Lewy.
El dominio numérico de dependencia (el stencil) tiene que contener al físico (la característica). CFL es necesaria para todo esquema explícito y nunca suficiente. FTCS puede cumplir CFL y aun así detonar. La explosión es causalidad rota, no un stencil corto.
Tres esquemas en cincuenta líneas de NumPy#
La misma malla, el mismo pulso cuadrado, el mismo CFL.
import numpy as np
N = 200
dx = 1.0 / N
u = 1.0
cfl = 0.8
dt = cfl * dx / u
n_steps = 400
x = (np.arange(N) + 0.5) * dx
q0 = ((x > 0.2) & (x < 0.4)).astype(float) # pulso cuadrado
def ftcs_advect(q, c):
return q - 0.5 * c * (np.roll(q, -1) - np.roll(q, 1))
def upwind_advect(q, c):
return q - c * (q - np.roll(q, 1)) # u > 0
def lax_wendroff_advect(q, c):
flux_diff = 0.5 * c * (np.roll(q, -1) - np.roll(q, 1))
visc = 0.5 * c * c * (np.roll(q, -1) - 2 * q + np.roll(q, 1))
return q - flux_diff + visc
q_ftcs, q_up, q_lw = q0.copy(), q0.copy(), q0.copy()
for _ in range(n_steps):
q_ftcs = ftcs_advect(q_ftcs, cfl)
q_up = upwind_advect(q_up, cfl)
q_lw = lax_wendroff_advect(q_lw, cfl)
# Solucion exacta: una vuelta completa volviendo al inicio
q_exact = q0
print("FTCS L1 err:", np.abs(q_ftcs - q_exact).sum() * dx)
print("Upwind L1 err:", np.abs(q_up - q_exact).sum() * dx)
print("LW L1 err:", np.abs(q_lw - q_exact).sum() * dx)Con cfl=0.8 y 400 pasos, las cifras aproximadas que deja este texto son:
- FTCS: la amplitud crece cerca de y pasa a NaN o
inf. - Upwind: el cuadrado se engorda hacia una forma gaussiana y el error L1 queda cerca de 0.04.
- Lax–Wendroff: la amplitud se conserva, pero quedan rizos (Gibbs) tras las esquinas.
c=0.5 es el que más abre el upwind#
El máximo de en 0.5 es el emborronado de la figura. En , vale cero y el upwind de primer orden desplaza el cuadrado una celda, intacto. queda en medio, en 0.16. Estable no quiere decir menos romo. 0.8 solo es menos viscoso que 0.5.
El primer orden es muy romo, pero el segundo trae nuevos dolores de cabeza#
La viscosidad upwind viene bien junto a un choque. Aplana oscilaciones no físicas. El mismo término sigue encendido en zonas suaves, así que el error queda atado al tamaño de una segunda derivada. Los códigos de producción eligen una de dos salidas.
- Usar un esquema de orden mayor (Lax–Wendroff, MUSCL, WENO) y añadir un limitador de flujo o de pendiente que baje el orden solo cerca de los choques. El cálculo que sujeta con un limitador el temblor de Lax–Wendroff en un escalón es esa elección.
- Llamar un solucionador de Riemann (Godunov, HLLC, Roe) en cada cara e integrar la causalidad de forma directa.
Los dos son mecanismos para decidir dónde se acepta la viscosidad y dónde se rechaza. El upwind de primer orden la acepta en todas las celdas. Simple, seguro y el más difusivo.
Llamar una vuelta a 400 pasos es un fallo#
Con , y , . Una vuelta de un dominio de longitud 1 pide pasos, es decir . Cuatrocientos pasos recorren . Un pulso de ancho 0.2, desplazado 0.6, pasa de a . Esos dos cuadrados no se solapan. La L1 del par nítido es 0.4.
La L1 upwind de 0.04 citada arriba no puede ser esa comparación. Leer 0.04 como el emborronado de una vuelta limpia exige 250 pasos. El upwind de primer orden en una dimensión aguanta hasta . Cuando lo que se transporta es una interfaz, ¿por qué el límite cae tanto? Donde la advección de interfaz se queda con un CFL de 0.05 muestra dónde se separan la longitud del stencil y la restricción de la interfaz.
Relacionados
Comparte si te resultó útil.