Traducción del original en coreano escrito por el autor. Leer el original (한국어)
Un solo nodo llevó el error de 0.21% a 76% — tiempo de relajación local en LBM de ley de potencia
En LBM de ley de potencia el tope de tau no es una perilla de estabilidad: es lo que permite alcanzar el estado estacionario.
Una línea con inf en un log que no convergía#
Un flujo en canal resuelto con lattice Boltzmann (LBM), modelando la sangre como fluido de ley de potencia (power-law). El campo de velocidad se veía razonable. El residual no bajaba. Tras veinte mil pasos seguía estacionado cerca de .
Al imprimir el tiempo de relajación nodo por nodo apareció un único inf en la línea central del canal. Ni un error de tipeo ni una división por cero. Ese nodo pedía, literalmente, viscosidad infinita.
LBM recupera el tensor de velocidad de deformación sin leer un vecino. El precio cae en un solo nodo, y un tope lo devuelve de 76% a 0.21%. La divergencia no es un bug. Es una propiedad de la propia ley de potencia. El deslizador del índice baja de 1.0 a 0.4 y mueve el del nodo central.
Uncapped, the centre node reads tau = infinity — the shear rate vanishes there, so a shear-thinning fluid asks for infinite viscosity. Green band 0.55 < tau < 2 is the usable range; red on the left is the stability edge, red on the right is where bounce-back walls start leaking.
El perfil de la izquierda se aplana en el centro mientras la escalera de la derecha entra en la banda roja. Al soltar cap tau, ese nodo sale del eje.
Dónde LBM regala la velocidad de deformación#
Añadir viscosidad no newtoniana a un código de volúmenes finitos empieza por el gradiente de velocidad. Hay que leer celdas vecinas, correr una reconstrucción — mínimos cuadrados, Green–Gauss, la que sea — y recién ahí aparece . En paralelo eso agrega otro intercambio de halos.
LBM se salta el paso. Siguiendo el desarrollo de Chapman–Enskog (una separación multiescala de la función de distribución en potencias del número de Knudsen) un orden, el segundo momento de la parte de no equilibrio queda ligado directamente al tensor de velocidad de deformación.
Aquí es la desviación del equilibrio en ese nodo, es la velocidad del sonido reticular al cuadrado y el tiempo de relajación. Todo el lado derecho vive dentro de un solo nodo. No se lee ningún vecino.
Ese mismo segundo momento, leído como déficit, es otra cuenta. Aquí ocurre lo contrario: el esfuerzo viscoso ya está dentro de las distribuciones, esperando a que lo lean.
La ley de potencia cierra con ese único .
es el índice de consistencia y el índice de la ley de potencia. Con el fluido es pseudoplástico (shear-thinning): cuanto más rápido se agita, más fluye. La sangre ronda . Con se vuelve al caso newtoniano.
La viscosidad está dentro de tau y tau dentro de la viscosidad#
Poniendo dos ecuaciones lado a lado el problema salta a la vista. En la colisión BGK, la viscosidad la fija el tiempo de relajación.
Pero también está en el denominador de la fórmula de . Hace falta para medir , hace falta para obtener , y hace falta para fijar . Cada nodo carga su propia ecuación no lineal pequeña. Dónde se pega el medio paso dentro de está en la expansión de segundo orden de la LBE discreta.
Muchas implementaciones la retrasan: reutilizan el del paso anterior y siguen. Eso funciona en estado estacionario. Donde el corte cambia rápido — a través de una interfase, en un ciclo pulsátil — la colisión usa una viscosidad atrasada un paso.
También se puede resolver de frente. La clave está en aislar la cantidad que no depende de . Llamando a la parte desviadora del segundo momento de no equilibrio y definiendo
resulta que se calcula solo con los actuales; no tiene por dónde entrar. Y .
Una ecuación local que cierra en un punto fijo#
Con el cambio de variable , las tres ecuaciones colapsan en una línea.
Una incógnita, ; un coeficiente constante, . La forma paga por una segunda razón. Llamando al lado derecho,
y en la raíz , de modo que . Por lo tanto siempre que . Para cualquier fluido pseudoplástico, la sustitución simple es una contracción incondicional. Sin Newton, sin salvaguardas, sin estimación inicial que ajustar.
En D2Q9 solo los cuatro enlaces diagonales alimentan . Los enlaces axiales quedan fuera de esa suma: su es cero.
Cinco topes distintos sobre el mismo canal#
Canal completamente desarrollado impulsado por una fuerza volumétrica, paredes con bounce-back a media malla, 31 nodos de ancho. El flujo en canal de ley de potencia tiene solución analítica, así que el error se mide en vez de estimarse a ojo.
es la fuerza volumétrica por unidad de masa y la semialtura. Con reaparece la parábola de siempre.
import numpy as np
CX = np.array([0, 1, 0, -1, 0, 1, -1, -1, 1])
CY = np.array([0, 0, 1, 0, -1, 1, 1, -1, -1])
W = np.array([4/9, 1/9, 1/9, 1/9, 1/9, 1/36, 1/36, 1/36, 1/36])
OPP = np.array([0, 3, 4, 1, 2, 7, 8, 5, 6])
CS2, G, NY = 1/3, 2e-6, 31
def eq(rho, ux):
cu = CX[:, None] * ux
return W[:, None] * rho * (1 + cu/CS2 + cu*cu/(2*CS2**2) - ux*ux/(2*CS2))
def relax_time(Q, rho, n, K, sweeps=40):
"""m = cs2*tau. Iteracion de punto fijo que nunca lee un nodo vecino."""
with np.errstate(divide='ignore', over='ignore', invalid='ignore'):
B = K * (Q / (2*rho))**(n - 1)
m = np.ones_like(Q)
for _ in range(sweeps):
m = CS2/2 + B * m**(1 - n)
return m / CS2
def exact(n, K):
h = NY/2.0
y = np.arange(NY) - (NY - 1)/2.0
return n/(n+1) * (G/K)**(1/n) * (h**((n+1)/n) - np.abs(y)**((n+1)/n))
def consistency_K(n, umax=8e-3):
h = NY/2.0
return G / (umax*(n+1)/(n*h**((n+1)/n)))**n
def channel(n, K, cap, steps=20000, tol=1e-12):
ue = exact(n, K)
f = eq(np.ones(NY), ue) # parte del perfil analitico y relaja solo la correccion
prev, tau = ue.copy(), np.full(NY, 0.8)
for it in range(steps):
rho = f.sum(0)
ux = (CX[:, None]*f).sum(0)/rho + 0.5*G
fe = eq(rho, ux)
Pxy = (CX[:, None]*CY[:, None]*(f - fe)).sum(0)
raw = relax_time(2*np.abs(Pxy), rho, n, K)
tau = np.clip(np.nan_to_num(raw, nan=cap, posinf=cap), 0.5005, cap)
cu = CX[:, None]*ux
src = W[:, None]*(1 - 1/(2*tau))*rho*G*((CX[:, None]-ux)/CS2 + cu*CX[:, None]/CS2**2)
post = f - (f - fe)/tau + src
for i in range(9):
f[i] = np.roll(post[i], CY[i])
for i in range(9): # bounce-back a media malla
if CY[i] == 1: f[i, 0] = post[OPP[i], 0]
if CY[i] == -1: f[i, -1] = post[OPP[i], -1]
if it % 200 == 199:
res = np.abs(ux - prev).max()/ux.max()
if res < tol: break
prev = ux.copy()
rho = f.sum(0)
ux = (CX[:, None]*f).sum(0)/rho + 0.5*G
err = np.linalg.norm(ux - ue)/np.linalg.norm(ue)
return err, res, it + 1, tau, raw
K1 = consistency_K(1.0)
e, r, it, tau, _ = channel(1.0, K1, 1e6)
print(f"Newtonian n=1.0 L2={e:.4%} tau={tau.min():.4f}..{tau.max():.4f} steps={it}")
n, K = 0.6, consistency_K(0.6)
_, _, _, _, raw = channel(n, K, 4.0, steps=200)
print(f"n=0.6 tau at wall {raw[0]:.4f} tau at centre {raw[NY//2]:.4e}")
print(f"{'cap':>9} {'L2 err':>9} {'residual':>10} {'steps':>7} {'capped':>8}")
for cap in [0.8, 1.5, 4.0, 40.0, 1e6]:
e, r, it, tau, _ = channel(n, K, cap)
print(f"{cap:9.1f} {e:9.4%} {r:10.2e} {it:7d} {int((tau >= cap - 1e-9).sum()):5d}/{NY}")Newtonian n=1.0 L2=0.1362% tau=0.5901..0.5901 steps=20000
n=0.6 tau at wall 0.5690 tau at centre inf
cap L2 err residual steps capped
0.8 0.2112% 1.08e-06 20000 3/31
1.5 0.2121% 1.14e-06 20000 1/31
4.0 0.2134% 1.07e-06 20000 1/31
40.0 0.4850% 1.02e-08 20000 1/31
1000000.0 75.9752% 7.69e-03 20000 1/31El control Pi_xy sube el momento de segundo orden y aparta la curva verde de la diagonal.
The staircase is the whole solver: 0 steps of m → cs2/2 + B m^(1-n) land on tau = 0.5894 (gamma = 2.04e-3, nu = 2.98e-2). Freezing tau at the previous step instead would answer 0.6011. No neighbour node is read at any point.
En pocos escalones la escalera se pega a la diagonal. Con por encima de 1 la pendiente cambia de signo, y la espiral sigue contrayendo mientras .
Lo que separó 0.21% de 76% fue un solo nodo#
La referencia newtoniana da 0.1362%, así que el solver en sí está sano. Cambiando a en la misma malla, sin tocar nada salvo el tope, el error oscila entre 0.2112% y 75.9752%.
Conviene leer la columna capped. Para cualquier tope de 1.5 o más, se recorta exactamente un nodo de 31: el de la línea central. Mantener ese único nodo en en lugar de 4.0 vale 75.76 puntos porcentuales de error.
La razón está en la colisión. En , hacer manda el prefactor a cero. Ese nodo nunca vuelve al equilibrio. El error que traía la distribución inicial se queda ahí y el streaming lo reparte a los vecinos. El residual clavado en es exactamente eso.
¿Por qué vale cero exacto en la línea central? Por simetría. Ahí cambia de signo, de modo que pasa por cero, y en el nivel discreto también se cancela de forma exacta. Entonces con da . El continuo dice lo mismo: la ley de potencia no está definida a velocidad de corte nula.
El nodo de pared imprime . Devolverlo a viscosidad da . El newtoniano de la misma corrida queda en , es decir . El piso del recorte, , deja y , dos órdenes por debajo de .
En la prueba de contracción, pone , así que . Los topes , y dan un L2 de , y . Entre y hay puntos; entre y hay . El tope sube el L2 a y deja el residual en , frente a con tope . Son más de tres órdenes, no un factor cerrado. Los pasos y se repiten en las cinco filas. Cambia el conteo: nodos recortados con , y a partir de . Un nodo de es la línea central. Tres de ya meten a los vecinos, donde ya no es cero.
Por qué el valor del tope casi no cambia la respuesta#
Aquí está lo que importa en la práctica. Los topes 0.8, 1.5 y 4.0 dan 0.2112%, 0.2121% y 0.2134%. Coinciden en tres dígitos.
Ese nodo casi no transporta esfuerzo de corte. El balance de cantidad de movimiento en un canal desarrollado fija el esfuerzo como , y en el centro , así que . La viscosidad puede estar tan mal como se quiera: la velocidad de corte que la multiplica es cero, así que nada llega al esfuerzo.
Lo que diverge es , no , y el flujo solo siente lo segundo. Por eso el tope no cuesta precisión. Subirlo a 40 duplica el error a 0.4850%, pero eso es un grande relajando ese nodo con lentitud: es un efecto de velocidad de convergencia, no de precisión.
Un tope demasiado bajo se paga del otro lado. Con 0.8 quedan recortados tres nodos. Los dos vecinos del centro resultan más fluidos de lo que corresponde, y ese error sí viaja en el esfuerzo. La tabla todavía marca 0.2112%, pero el conteo de recortados sube rápido a medida que baja. En la primera simulación, poniendo nodes en 81 y bajando a 0.4 se ve llenarse la banda roja.
Dónde cambia la historia para la sangre#
Que la ley de potencia explote a corte nulo es un defecto conocido en reología, no solo en la discretización. La sangre real tiende a una viscosidad finita a corte cero. Carreau–Yasuda corrige justamente ese extremo.
y cierran ambos extremos y es el inverso de la velocidad de corte donde empieza el adelgazamiento. Con este modelo cuando , finito. No hace falta un tope puesto a mano: es el tope.
¿Entonces para qué usar la ley de potencia? Fuera del centro del conducto los dos modelos difieren poco, y la ley de potencia trae una solución analítica contra la cual verificar. Además, el punto fijo de más arriba cierra en una línea solo para la ley de potencia. Carreau–Yasuda itera igual, pero la prueba de contracción no queda ni de cerca tan limpia.
Del lado de LBM hay algo más que vigilar cuando crece: la posición efectiva de la pared bounce-back se desplaza con . Un fluido pseudoplástico tiene pequeño cerca de la pared, así que ese error incluso se reduce. El precio es el margen de estabilidad cuando se acerca a . El nodo de pared de arriba quedó en 0.5690: hay margen, pero no sobra. , y esa es la holgura hasta el piso.
Divergir y ser inservible no son lo mismo#
inf no es una división por cero. Con cizalla nula y , es la respuesta correcta. El caso se detiene porque BGK usa como coeficiente. "Viscosidad infinita" y "este nodo ya no se relaja" quedan escritos en la misma línea.
El tope corta esa segunda lectura, y la lectura es de la discretización. En la tabla, y dejan el L2 en y . Con la misma fórmula del canal vuelve a la parábola, y esa línea base está en la solución analítica de Poiseuille. Si el log marca claramente más de un nodo recortado, lo que hay que cambiar es o la malla, no el tope.
Relacionados
Comparte si te resultó útil.