Traducción del original en coreano escrito por el autor. Leer el original (한국어)
Dar a cada especie su propio tau desvió la masa total un 16.8% — velocidad de corrección en LBM multicomponente
En cuanto dos especies reciben difusividades distintas, la continuidad se rompe. Una línea de velocidad de corrección convierte 0.168 en 0.0005.
El día en que la tercera especie descuadró el libro de densidades#
Cada especie que se agrega a un solver de combustión trae consigo otro juego de funciones de distribución. Cada una difunde a su propio ritmo, así que cada una recibe su propio tiempo de relajación . Hasta aquí, manual de texto. Tras unos cientos de pasos, se aleja de 1. Las fracciones másicas (la porción de la masa total que lleva cada especie) tienen que sumar 1 por definición.
Este artículo rastrea esa desviación hasta su origen con un desarrollo de Chapman–Enskog y luego la deshace con una sola línea. Una mezcla ternaria corre 2000 pasos y el déficit máximo cae de 0.168 a 0.0005. La conclusión por delante: no es un bug, es el modelo. En cuanto las especies reciben distintos, la continuidad está construida para romperse.
Tres juegos de funciones de distribución, repartidos por tarea#
Un LBM compresible multifásico multicomponente separa sus distribuciones según su función. lleva el campo de flujo, la energía, la especie -ésima. Las tres viven sobre las mismas velocidades de red y resuelven la misma ecuación de Boltzmann discreta.
es la distribución de la especie en la dirección , su tiempo de relajación y el paso temporal.
El equilibrio solo necesita la densidad de especie y la velocidad del flujo . A diferencia de , no lleva término de segundo orden, porque la ecuación de especies solo debe recuperar advección y difusión.
son los pesos de red y la velocidad del sonido de red. La densidad de especie se lee como y la fracción másica como .
Al separar los deslizadores , las tres difusividades se abren y la suma de masa del panel inferior se aparta de 1.
step 0 — current |sum Y_k - 1| = 0.00e+0, peak = 0.00e+0. Drag the three sliders to the same value and the lower panel flattens to round-off. Spread them apart and the error grows every step: each species relaxes with its own tau, so the three Fickian fluxes no longer cancel. Tick the checkbox to inject the correction velocity and the growth stops on the spot.
Al alinear los tres deslizadores, el panel inferior se aplana hasta el redondeo. Dejarlos separados hace que el error se acumule en cada paso. La casilla es la velocidad de corrección. Al activarla, la suma se pliega otra vez hacia 1.
Lo que Chapman–Enskog extrae de #
Se expande la ecuación discreta en serie de Taylor en y se separa la distribución como . Al recolectar el momento de orden cero por órdenes aparece una ecuación de advección–difusión para una sola especie.
es la difusividad de esa especie. El proviene de la discretización, no de la física. Ese mismo aparece como viscosidad en el campo de flujo y como difusividad térmica en el de energía. Al atar ambos libros contables, el número de Prandtl queda fijado a una constante — eso está en las dos constantes escondidas en el LBM térmico.
Hasta aquí todo se ve limpio. Basta girar un para que la difusividad caiga donde se quiera. Si de verdad ocurre así se mide más abajo.
Qué queda cuando los difieren#
El problema no aparece en una ecuación de especie sino en su suma. Se suma la ecuación sobre y se usa .
El lado izquierdo es la continuidad. El derecho debe anularse. En general no lo hace.
Solo cuando todos los son iguales se cumple . Dar a cada especie su propio es exactamente el acto de romper esa cancelación. Escrito con flujos queda aún más claro: los flujos de Fick no suman cero.
Físicamente es un hecho conocido. La ley de Fick es una aproximación de mezcla binaria, y con tres o más especies el cierre correcto son las relaciones de Stefan–Maxwell. El LBM hereda el déficit completo al transcribir esa aproximación como un independiente por especie.
Dos mil pasos de una mezcla ternaria, y el cuadre de cuentas#
Coloqué tres juegos de poblaciones de especie sobre una red D1Q3. La mezcla está en reposo: , . No ocurre nada salvo difusión, de modo que debe quedarse en 1 para siempre. Primero un modo seno amortiguado verifica si realmente vale , y después se mide el déficit con varias combinaciones de .
import numpy as np
N, CS2 = 256, 1.0/3.0
W = np.array([2.0/3.0, 1.0/6.0, 1.0/6.0]) # pesos D1Q3: c = 0, +1, -1
C = np.array([0, 1, -1])
def feq_species(rho_k, u):
return rho_k[None, :] * W[:, None] * (1.0 + C[:, None] * u[None, :] / CS2)
def correction_velocity(rho_k, D):
dY = np.array([(np.roll(r, -1) - np.roll(r, 1)) * 0.5 for r in rho_k])
return np.sum(D[:, None] * dY, axis=0) # V_c = sum_k D_k grad Y_k
def lbm_species_step(h, D, use_correction):
rho_k = h.sum(axis=1) # (K, N)
u = correction_velocity(rho_k, D) if use_correction else np.zeros(N)
tau = D / CS2 + 0.5
for k in range(len(D)):
h[k] += (feq_species(rho_k[k], u) - h[k]) / tau[k]
for i in range(3):
h[k, i] = np.roll(h[k, i], C[i])
return h
def diffusion_leak_run(D, steps, use_correction):
x = np.arange(N)
r1 = 0.30 + 0.20 * np.sin(2 * np.pi * x / N)
r2 = 0.45 + 0.15 * np.cos(4 * np.pi * x / N)
r3 = 1.0 - r1 - r2 # al inicio la suma es exactamente 1
h = np.array([feq_species(r, np.zeros(N)) for r in [r1, r2, r3]])
worst = 0.0
for _ in range(steps):
h = lbm_species_step(h, D, use_correction)
worst = max(worst, np.abs(h.sum(axis=(0, 1)) - 1.0).max())
return worst
def measure_D_eff(tau, steps=400):
x = np.arange(N)
amp0 = 0.01
rho = 0.5 + amp0 * np.sin(2 * np.pi * x / N) # inyectar un modo seno y medir su decaimiento
h = feq_species(rho, np.zeros(N))
for _ in range(steps):
r = h.sum(axis=0)
h += (feq_species(r, np.zeros(N)) - h) / tau
for i in range(3):
h[i] = np.roll(h[i], C[i])
amp = np.abs(np.fft.rfft(h.sum(axis=0))[1]) * 2.0 / N
k2 = (2 * np.pi / N) ** 2
return -np.log(amp / amp0) / (k2 * steps)
print("tau D_theory=cs^2(tau-1/2) D_measured error[%]")
for tau in (0.55, 0.80, 1.20, 2.00):
dth, dm = CS2 * (tau - 0.5), measure_D_eff(tau)
print(f"{tau:.2f} {dth:.6f} {dm:.6f} {100*(dm-dth)/dth:+.3f}")
print()
print("D1,D2,D3 correction max|sum(rho_k)-1|")
for D in (np.array([0.05, 0.05, 0.05]),
np.array([0.05, 0.10, 0.02]),
np.array([0.01, 0.10, 0.30]),
np.array([0.005, 0.10, 0.50])):
for corr in (False, True):
print(f"{D[0]:.3f},{D[1]:.3f},{D[2]:.3f} {str(corr):5s} "
f"{diffusion_leak_run(D, 2000, corr):.3e}")tau D_theory=cs^2(tau-1/2) D_measured error[%]
0.55 0.016667 0.016874 +1.243
0.80 0.100000 0.100137 +0.137
1.20 0.233333 0.233122 -0.091
2.00 0.500000 0.498135 -0.373
D1,D2,D3 correction max|sum(rho_k)-1|
0.050,0.050,0.050 False 1.865e-13
0.050,0.050,0.050 True 2.091e-13
0.050,0.100,0.020 False 5.050e-02
0.050,0.100,0.020 True 5.201e-05
0.010,0.100,0.300 False 1.155e-01
0.010,0.100,0.300 True 1.354e-04
0.005,0.100,0.500 False 1.683e-01
0.005,0.100,0.500 True 5.215e-04Al separar un deslizador , cambia la longitud de la flecha roja resultante.
sum_k J_k = 0.00e+0, V_c = 0.0000. With three different D_k the red resultant almost never lands on zero, whatever the gradients — that residue is exactly the mass the solver invents each step. Switch the correction on and the green segments rebalance the three arrows so the resultant collapses to zero for every slider setting.
Con cualquier combinación de y gradientes, la flecha resultante roja casi nunca cae en cero. Al marcar la casilla aparecen los segmentos verdes y la resultante se pliega hasta cero exacto.
Conviene leer primero la tabla de arriba. se cumple al nivel del 0.1%. El 1.24% en es el error de red que crece a medida que se acerca a . La relación en sí es confiable.
La tabla de abajo es el punto. Con las tres difusividades en 0.05, el déficit vale , redondeo de doble precisión. Separarlas por un factor 2.5 ya da . Separarlas por 100 lleva a 0.168. Con , eso es el 16.8% de la masa total.
Al meter en sale la columna teórica de arriba. Con , . La medida es 0.100137, error . Con , , medida 0.498135, error . El signo cambia. Con , frente a una medida de 0.016874, . Con la teoría es 0.233333, la medida 0.233122, . Cuanto más lejos de , más chico el error porcentual.
Los cocientes del déficit también salen de la tabla inferior. Para , sobre da 971. Para , sobre da 323. Un factor 100 entre difusividades compra una corrección menor que un factor 2.5. Con los tres valores en 0.05 el déficit es , y con la corrección activa queda en . La cancelación ya vale, así que la velocidad de corrección no tiene trabajo. En 2000 pasos con , 0.168 es el 16.8% de la masa, y es el residuo de ese hueco.
La línea que convirtió 0.168 en 0.0005#
El arreglo se conoce desde hace mucho. Se suma a todas las especies la misma velocidad de corrección , forzando que los flujos sumen cero.
Con ese queda . Usa directamente la restricción .
En LBM esto nunca se convierte en un término fuente. Basta cambiar la velocidad dentro del equilibrio de a : la línea correction_velocity y la rama use_correction de arriba son todo el cambio. El flujo de más que aparece al subir la velocidad vive en el término sobrante de un LBM de convección–difusión.
La tabla dice lo mismo. Un déficit de pasa a , y pasa a : factores de 971 y 323.
Por qué la corrección aún no llega a cero#
Hay un detalle que salta a la vista. Con difusividades iguales el déficit es , pero con la corrección activa se estanca cerca de . Eso no es precisión de máquina.
La razón es que hay dos operadores discretos en juego. correction_velocity construye con una diferencia central. El flujo difusivo que el LBM produce realmente es el primer momento de la parte de no equilibrio , es decir, otro gradiente discreto definido por el streaming. Ambos discrepan en , y esa discrepancia sobrevive en vez de cancelarse.
Para eliminarla conviene tomar la velocidad de corrección del mismo momento de no equilibrio, algo como . La diferencia central también va un paso atrasada, lo que deja un residuo por el mismo motivo. La idea general — que una restricción discreta transcrita tal cual del continuo no se satisface de forma exacta — es el mismo tipo de hueco que el defecto del momento cúbico del equilibrio LBM.
En la práctica, eso sí, y son cosas muy distintas. El primero no se acumula y baja al refinar la malla. El segundo crece con el tiempo.
Dónde asoma este término en un código de combustión#
Los números de Lewis en combustión metano–aire se dispersan entre 0.3 y 1.8. H y H son extremadamente rápidos; los hidrocarburos grandes, lentos. En difusividad eso es un rango de más de veinte. La tercera fila de la tabla cae justo ahí.
El déficit no se queda en un error de densidad. Las tasas de reacción dependen de de forma exponencial. Si la suma pasa de 1, la tasa se sobreestima, ese calor vuelve a empujar la densidad y la corrida diverge. Muchos códigos renormalizan dividiendo por la suma en cada paso, pero eso no elimina el déficit: lo reparte de manera arbitraria entre especies. Qué especie paga la cuenta depende del índice del nodo.
El remedio más común en producción es designar la especie más pesada como especie de relleno (bath species) y calcular de forma directa. La suma queda exactamente en 1, pero todo el déficit se apila sobre el N. La velocidad de corrección reparte esa carga en proporción a .
Volcar el déficit sobre N cuadra el libro en la especie equivocada#
Al dar a cada especie su propio se abren tres caminos. Dejar el déficit donde está, dividir por la suma y cargarlo sobre una especie, o repartirlo con una velocidad de corrección en proporción a . Dejarlo no es un camino. Cargarlo sobre una especie solo se sostiene cuando esa especie de relleno pesa mucho, combustión diluida con . El valor por defecto es la velocidad de corrección. El costo es un juego de gradientes por paso y una velocidad cambiada en el equilibrio.
El rango de se cierra al mismo tiempo. La tabla muestra un error de difusividad de en y de en . El signo cambia. Ese piso es el mismo sitio que el medio paso que lee mal la viscosidad por un factor 51 en . A lo largo del eje de especies el piso se tiende una vez más. Cuando un registro imprime , conviene alinear primero los . Si difieren, la causa ya está en esa línea.
Relacionados
Comparte si te resultó útil.