Skip to content
cfd-lab:~/es/posts/2026-09-04-lbm-double-di…● online

Traducción del original en coreano escrito por el autor. Leer el original (한국어)

NOTE #149DAY FRI CFD기법DATE 2026.09.04UPDATED 2026.10.19READ 10 min read#Double-Distribution-Function#LBM#Prandtl-Number#Heat-Transfer#Chapman-Enskog

Duplicar τ dejó Pr en 1.0000 — las dos constantes encerradas en el LBM térmico

Con un solo τ, Pr = 1 y γ = 1 + 2/D no son propiedades del fluido sino valores que fijó la retícula. Liberar ambos exige una función de distribución aparte para la energía.

Un valor que nunca ingresé salió como 1.0000#

Sobre una retícula D2Q9 coloqué una onda de corte sinusoidal y una onda de temperatura sinusoidal, y medí la viscosidad cinemática ν\nu y la difusividad térmica α\alpha a partir de la rapidez con que decae cada amplitud. Repetí la medición duplicando el tiempo de relajación τ\tau: 0.6, 0.8, 1.2. Las tres veces el número de Prandtl (la razón entre difusión de momento y difusión de calor) dio 1.0001, 1.0000 y 1.0001.

Ese valor nunca entró como propiedad del fluido. Lo fijó la retícula.

Este artículo señala en qué línea de código está ese candado y vuelve a medir, sobre la misma retícula, qué se libera al levantar una segunda función de distribución para la energía. La constante encerrada no es solo Pr\mathrm{Pr}. La razón de calores específicos γ\gamma también está encerrada, y en D2Q9 vale 2, no el 1.4 del aire. Y aun después de liberarla, τg\tau_g no se puede empujar sin límite: dónde se rompe también se mide con números.

Abajo se puede abrir y cerrar el candado a mano.

nu 0.1000alpha 0.1000Pr 1.000step 0A_u 1.000A_T 1.000
Locked, the orange curve hides underneath the blue one at every tau_f you try — one relaxation time cannot hold two transport coefficients apart. Unlock it and drag tau_g: the thermal wave now outlives the shear wave (Pr > 1) or dies first (Pr < 1).

Con el candado puesto, mover τf\tau_f no sirve de nada: la curva naranja (temperatura) queda totalmente escondida bajo la azul (velocidad). Al soltar el candado y arrastrar τg\tau_g, las dos curvas se separan. Cuánto se separan es justamente Pr\mathrm{Pr}.

Un solo τ se usa en dos lugares#

Esta es la ecuación de Boltzmann en retícula con el término de colisión BGK.

fi(x+eiΔt,  t+Δt)−fi(x,t)=−Δtτ[fi−fieq]f_i(\boldsymbol{x} + \boldsymbol{e}_i \Delta t,\; t + \Delta t) - f_i(\boldsymbol{x}, t) = -\frac{\Delta t}{\tau}\left[ f_i - f_i^{\mathrm{eq}} \right]

fif_i es la función de distribución en la dirección ii de la retícula, ei\boldsymbol{e}_i es la velocidad discreta en esa dirección y τ\tau es el tiempo de relajación. Al llevar el desarrollo de Chapman–Enskog (un desarrollo que toma el alejamiento del equilibrio como parámetro pequeño y separa el resultado orden por orden) hasta primer orden, el esfuerzo viscoso sale de la parte de no equilibrio de primer orden de ff. El resultado es esta expresión conocida.

ν=cs2(τ−Δt2)\nu = c_s^{2}\left(\tau - \frac{\Delta t}{2}\right)

csc_s es la velocidad del sonido de la retícula y Δt/2\Delta t/2 es la corrección que dejó la discretización. El mismo desarrollo deja un flujo de más junto a la convección, medido en el LBM en el que subir la velocidad recorta la difusión.

El problema viene después. Si la energía interna se define como segundo momento de esa misma ff, la ecuación de temperatura sale del mismo desarrollo a través del mismo término de no equilibrio de primer orden. La difusividad térmica queda con la forma idéntica.

α=cs2(τ−Δt2)\alpha = c_s^{2}\left(\tau - \frac{\Delta t}{2}\right)

Los lados derechos coinciden carácter por carácter. De ahí solo se sigue una conclusión.

Pr=να=1\mathrm{Pr} = \frac{\nu}{\alpha} = 1

La razón cabe en una línea. El flujo de momento y el flujo de calor salen del mismo término de no equilibrio de la misma función de distribución, y delante de ese término hay una sola constante de tiempo. Con una sola constante, la razón entre ambos no es algo que se pueda elegir.

Que Pr\mathrm{Pr} ronde 1 en los gases es un hecho experimental, y de ahí sale también la analogía de Reynolds que enlaza fricción y transferencia de calor. Pero allí es una aproximación y una elección de modelado. Aquí es una imposición. Con agua o con metal líquido el resultado sigue siendo 1.

Levantar una función de distribución aparte para la energía#

La solución es estructuralmente simple. El problema nació de tener una sola constante, así que se crea una segunda. ff se encarga solo de masa y momento, y la energía queda a cargo de una segunda función de distribución gig_i. Es el método de doble función de distribución (DDF).

Las condiciones de momento que gg debe cumplir ocupan dos líneas.

∑igi=ρE,∑iei gi=ρEu+p u\sum_i g_i = \rho E, \qquad \sum_i \boldsymbol{e}_i\, g_i = \rho E \boldsymbol{u} + p\,\boldsymbol{u}

E=cvT+∣u∣2/2E = c_v T + |\boldsymbol{u}|^{2}/2 es la energía total por unidad de masa y pup\boldsymbol{u} es el trabajo de la presión. La clave está en ese pup\boldsymbol{u} de la segunda línea. El flujo convectivo de energía no es solo ρEu\rho E \boldsymbol{u}, sino ρHu\rho H \boldsymbol{u}, con el trabajo de presión incluido, y por eso la distribución de equilibrio de gg no puede copiar tal cual la de ff.

Al relajar gg con τg\tau_g y correr el mismo desarrollo de Chapman–Enskog, la difusividad térmica ahora mira a τg\tau_g.

Pr=να=τf−Δt/2τg−Δt/2\mathrm{Pr} = \frac{\nu}{\alpha} = \frac{\tau_f - \Delta t/2}{\tau_g - \Delta t/2}

El número de Reynolds fija τf\tau_f y el número de Prandtl fija τg\tau_g. Cada exigencia pasó a tener su propia perilla.

Midiendo el candado y su liberación en la misma retícula con Python#

En lugar de dejarlo en palabras, lo medí. Armé ff en D2Q9 y gg en D2Q5 (una retícula de cinco velocidades solo para temperatura), con una onda sinusoidal que varía únicamente en yy como condición inicial. La amplitud de la onda de corte decae como exp⁡(−νk2t)\exp(-\nu k^{2} t) y la de la onda térmica como exp⁡(−αk2t)\exp(-\alpha k^{2} t). Un ajuste por mínimos cuadrados del logaritmo de la amplitud devuelve ν\nu y α\alpha.

import math
 
NY, CS2 = 64, 1.0 / 3.0
K = 2.0 * math.pi / NY
 
EX9 = [0, 1, 0, -1, 0, 1, -1, -1, 1]
EY9 = [0, 0, 1, 0, -1, 1, 1, -1, -1]
W9 = [4/9, 1/9, 1/9, 1/9, 1/9, 1/36, 1/36, 1/36, 1/36]
 
EY5 = [0, 0, 1, 0, -1]
W5 = [1/3, 1/6, 1/6, 1/6, 1/6]
 
 
def feq_d2q9(rho, ux, uy):
    u2 = ux * ux + uy * uy
    return [w * rho * (1 + 3 * (ex * ux + ey * uy)
                       + 4.5 * (ex * ux + ey * uy) ** 2 - 1.5 * u2)
            for w, ex, ey in zip(W9, EX9, EY9)]
 
 
def geq_d2q5(temp):
    return [w * temp for w in W5]
 
 
def fit_decay_rate(samples):
    """samples = [(paso, amplitud)] -> pendiente de ln(amplitud) por mínimos cuadrados."""
    n = len(samples)
    xs = [s for s, _ in samples]
    ys = [math.log(a) for _, a in samples]
    mx, my = sum(xs) / n, sum(ys) / n
    num = sum((x - mx) * (y - my) for x, y in zip(xs, ys))
    den = sum((x - mx) ** 2 for x in xs)
    return -num / den
 
 
def run_shear_wave(tau_f, steps=3000, amp=1e-3):
    f = [[0.0] * NY for _ in range(9)]
    for y in range(NY):
        for i, v in enumerate(feq_d2q9(1.0, amp * math.sin(K * y), 0.0)):
            f[i][y] = v
    log = []
    for step in range(steps + 1):
        rho = [sum(f[i][y] for i in range(9)) for y in range(NY)]
        ux = [sum(f[i][y] * EX9[i] for i in range(9)) / rho[y] for y in range(NY)]
        if step % 200 == 0:
            a = 2.0 / NY * sum(ux[y] * math.sin(K * y) for y in range(NY))
            log.append((step, a))
        post = [[0.0] * NY for _ in range(9)]
        for y in range(NY):
            eq = feq_d2q9(rho[y], ux[y], 0.0)
            for i in range(9):
                post[i][y] = f[i][y] - (f[i][y] - eq[i]) / tau_f
        for i in range(9):
            for y in range(NY):
                f[i][(y + EY9[i]) % NY] = post[i][y]
    return fit_decay_rate(log) / (K * K)
 
 
def run_thermal_wave(tau_g, amp=1e-3):
    """El número de pasos se ajusta a tau_g para que la amplitud siempre caiga e^-2.5."""
    alpha_th = CS2 * (tau_g - 0.5)
    steps = max(240, min(12000, int(2.5 / (alpha_th * K * K))))
    every = max(1, steps // 12)
    g = [[0.0] * NY for _ in range(5)]
    for y in range(NY):
        for i, v in enumerate(geq_d2q5(amp * math.sin(K * y))):
            g[i][y] = v
    log = []
    for step in range(steps + 1):
        temp = [sum(g[i][y] for i in range(5)) for y in range(NY)]
        if step % every == 0:
            a = 2.0 / NY * sum(temp[y] * math.sin(K * y) for y in range(NY))
            log.append((step, a))
        post = [[0.0] * NY for _ in range(5)]
        for y in range(NY):
            eq = geq_d2q5(temp[y])
            for i in range(5):
                post[i][y] = g[i][y] - (g[i][y] - eq[i]) / tau_g
        for i in range(5):
            for y in range(NY):
                g[i][(y + EY5[i]) % NY] = post[i][y]
    return fit_decay_rate(log) / (K * K)
 
 
def tau_for(nu, target_pr):
    return 0.5 + nu / (target_pr * CS2)
 
 
TAU_F = 0.8
nu = run_shear_wave(TAU_F)
print(f"tau_f = {TAU_F}   nu(theory) = {CS2*(TAU_F-0.5):.6f}   nu(measured) = {nu:.6f}")
print()
print("[A] single distribution: one tau relaxes momentum AND energy")
print(f"{'tau':>6} {'nu':>10} {'alpha':>10} {'Pr':>8}")
for t in (0.6, 0.8, 1.2):
    n_, a_ = run_shear_wave(t), run_thermal_wave(t)
    print(f"{t:6.2f} {n_:10.6f} {a_:10.6f} {n_/a_:8.4f}")
print()
print("[B] double distribution: tau_g chosen for a target Pr (tau_f = 0.8)")
print(f"{'gas':>8} {'Pr(target)':>11} {'tau_g':>8} {'alpha':>10} {'Pr(meas)':>9} {'err%':>7}")
for name, pr in (("mercury", 0.025), ("air", 0.71), ("Pr=1", 1.0), ("water", 7.0)):
    tg = tau_for(nu, pr)
    a_ = run_thermal_wave(tg)
    prm = nu / a_
    print(f"{name:>8} {pr:11.3f} {tg:8.4f} {a_:10.6f} {prm:9.4f} {100*(prm-pr)/pr:7.2f}")
 
print()
print("[C] how far can tau_g be pushed?  (theory: alpha = cs2*(tau_g-0.5))")
print(f"{'tau_g':>7} {'alpha(th)':>10} {'alpha(meas)':>12} {'err%':>7}")
for tg in (0.51, 0.55, 0.7, 1.0, 2.0, 4.0, 8.0, 12.5):
    th = CS2 * (tg - 0.5)
    ms = run_thermal_wave(tg)
    print(f"{tg:7.2f} {th:10.5f} {ms:12.5f} {100*(ms-th)/th:7.2f}")
tau_f = 0.8   nu(theory) = 0.100000   nu(measured) = 0.100057
 
[A] single distribution: one tau relaxes momentum AND energy
   tau         nu      alpha       Pr
  0.60   0.033368   0.033363   1.0001
  0.80   0.100057   0.100060   1.0000
  1.20   0.233144   0.233124   1.0001
 
[B] double distribution: tau_g chosen for a target Pr (tau_f = 0.8)
     gas  Pr(target)    tau_g      alpha  Pr(meas)    err%
 mercury       0.025  12.5069   2.047239    0.0489   95.50
     air       0.710   0.9228   0.140963    0.7098   -0.03
    Pr=1       1.000   0.8002   0.100117    0.9994   -0.06
   water       7.000   0.5429   0.014308    6.9931   -0.10
 
[C] how far can tau_g be pushed?  (theory: alpha = cs2*(tau_g-0.5))
  tau_g  alpha(th)  alpha(meas)    err%
   0.51    0.00333      0.00334    0.16
   0.55    0.01667      0.01668    0.10
   0.70    0.06667      0.06672    0.08
   1.00    0.16667      0.16667   -0.00
   2.00    0.50000      0.49624   -0.75
   4.00    1.16667      1.11274   -4.62
   8.00    2.50000      1.94812  -22.08
  12.50    4.00000      2.04752  -48.81

Al subir n_0, la separación entre los dos pulsos acústicos se reduce y la marca azul asciende hacia la línea del aire.

gamma 2.000c_v 1.00 Rsound speed 0.0%
Start at n0 = 0 with D2Q9: gamma = 2, and the blue pulse runs 19% fast against air. Drag n0 until the blue marker lands on the dashed line — the number you land on is how many internal degrees of freedom the energy distribution has to carry.

En D2Q9 la marca toca la línea punteada en n0=3n_0 = 3, γ=1.400\gamma = 1.400. En tres dimensiones el mismo 1.400 aparece en n0=2n_0 = 2.

La tabla [A] es el candado. Al duplicar τ\tau de 0.6 a 1.2, ν\nu crece siete veces y aun así Pr\mathrm{Pr} sigue en 1 hasta el cuarto decimal. La tabla [B] es la liberación. El aire queda en 0.7098 y el agua en 6.9931, ambos a menos de 0.1% del objetivo. La excepción es la primera fila: el mercurio falla por 95%. Esa fila tiene su propia sección más adelante.

Hay una segunda constante encerrada: la razón de calores específicos#

Quedarse en Pr\mathrm{Pr} deja pasar el segundo candado. Una partícula sobre la retícula se mueve solo en DD direcciones traslacionales. Ni rotación ni vibración. Entonces el calor específico a volumen constante cuenta únicamente los grados de libertad traslacionales, queda cv=DR/2c_v = DR/2, y la constante del gas se recupera como R=cv/(D/2)R = c_v / (D/2). La razón de calores específicos queda decidida sola.

cv=(D+n0) R2,γ=1+2D+n0c_v = \frac{(D + n_0)\,R}{2}, \qquad \gamma = 1 + \frac{2}{D + n_0}

n0n_0 es la cantidad de grados de libertad internos que se cargan además de los traslacionales. Sin hacer nada, n0=0n_0 = 0.

Retículan0n_0cvc_vγ\gammaGas correspondiente
D2Q901.0R1.0R2.000ninguno
D3Q1901.5R1.5R1.667monoatómico (Ar, He)
D2Q932.5R2.5R1.400aire
D3Q1922.5R2.5R1.400aire
D2Q943.0R3.0R1.333vapor de agua

En dos dimensiones, una retícula sin retocar tiene γ=2\gamma = 2. Como la velocidad del sonido es γRT\sqrt{\gamma R T}, eso da 2/1.4=1.195\sqrt{2/1.4} = 1.195 veces la del aire, es decir un 19.5% más rápida. El número de Mach, los ángulos de choque y la condición de bloqueo de una tobera se desvían todos en la misma proporción. En cálculos compresibles esto molesta antes que Pr\mathrm{Pr}.

El número que quedó sobre la línea punteada de arriba es la fila del aire en esta tabla. D2Q9 pide n0=3n_0 = 3, D3Q19 pide n0=2n_0 = 2, y ambos dan γ=1.400\gamma = 1.400. Una D2Q9 dejada en n0=0n_0 = 0 conserva γ=2.000\gamma = 2.000, y la velocidad del sonido sale 2/1.4=1.195\sqrt{2/1.4} = 1.195 veces la del aire, un 19.5% más rápida.

Hasta dónde se puede empujar τ_g#

La tabla [C] mide hasta cuándo es confiable α=cs2(τg−Δt/2)\alpha = c_s^{2}(\tau_g - \Delta t/2). Hasta τg=2\tau_g = 2 el error se mantiene por debajo de 0.8%. En 4 es 4.6%, en 8 llega a 22% y en 12.5 la brecha se abre a 49%. Sale apenas la mitad del valor teórico.

La razón está en el origen de esa fórmula. α=cs2(τg−Δt/2)\alpha = c_s^{2}(\tau_g - \Delta t/2) es un resultado de primer orden del desarrollo de Chapman–Enskog. Para que el desarrollo valga, el tiempo de relajación debe ser corto frente a la escala temporal del flujo. Cuando τg\tau_g crece, el término de segundo orden descartado —un término hiperdifusivo proporcional a la cuarta potencia del número de onda— crece hasta el tamaño del de primer orden. El techo práctico ronda α≈0.5\alpha \approx 0.5 en unidades de retícula.

Por eso se rompió la fila del mercurio en [B]. Obtener Pr=0.025\mathrm{Pr} = 0.025 con τf=0.8\tau_f = 0.8 exige α=4.0\alpha = 4.0, ocho veces ese techo. La receta no es subir más τg\tau_g, sino bajar ν\nu. Para alcanzar Pr=0.025\mathrm{Pr} = 0.025 respetando α≤0.5\alpha \le 0.5 hace falta ν≤0.0125\nu \le 0.0125, o sea τf≤0.5375\tau_f \le 0.5375. Y ahí aparece la pared del otro lado: cuando τf\tau_f se pega a 0.5, BGK se vuelve inestable.

Los bordes de esa ventana están impresos en la tabla [C]. Con τg=2.00\tau_g = 2.00, α\alpha teórico vale 0.50000, medido 0.49624, error −0.75-0.75%. Con τg=4.00\tau_g = 4.00 la teoría da 1.16667, la medición 1.11274, error −4.62-4.62%. Con τg=8.00\tau_g = 8.00, teoría 2.50000, medición 1.94812, error −22.08-22.08%. Con τg=12.50\tau_g = 12.50 la teoría dice 4.00000 y el cálculo devuelve 2.04752, error −48.81-48.81%, casi la mitad fuera. Con τg=0.51\tau_g = 0.51 es al revés: teoría 0.00333, medición 0.00334, error 0.16%, todavía dentro de la fórmula.

El mercurio de [B] pedía Pr=0.025\mathrm{Pr} = 0.025 con τg=12.5069\tau_g = 12.5069. Salió α=2.047239\alpha = 2.047239, Pr\mathrm{Pr} medido 0.0489, err% 95.50. El aire de la misma tabla, con τg=0.9228\tau_g = 0.9228, queda en Pr=0.7098\mathrm{Pr} = 0.7098, err% −0.03-0.03. El agua, con τg=0.5429\tau_g = 0.5429, queda en 6.9931, err% −0.10-0.10. La fila Pr=1\mathrm{Pr}=1 usa τg=0.8002\tau_g = 0.8002 y mide 0.9994. 0.71 y 7 caben en la ventana. 0.025 queda fuera.

Medida con la misma regla, la tabla [A] muestra un candado más plano. Con τ=0.60\tau = 0.60, ν=0.033368\nu = 0.033368, α=0.033363\alpha = 0.033363, Pr=1.0001\mathrm{Pr} = 1.0001. Con τ=1.20\tau = 1.20, ν=0.233144\nu = 0.233144, α=0.233124\alpha = 0.233124, Pr=1.0001\mathrm{Pr} = 1.0001. Al duplicar τ\tau, ν\nu pasa de 0.033 a 0.233, unas siete veces, y la razón sigue en 1 en el cuarto decimal. Para τf=0.8\tau_f = 0.8 la teoría es cs2(τ−1/2)=(1/3)(0.3)=0.100000c_s^{2}(\tau - 1/2) = (1/3)(0.3) = 0.100000 y la medición es 0.100057. La onda de corte ya cuadra. Lo encerrado es la razón. Mantener α≤0.5\alpha \le 0.5 y aun así llegar a Pr=0.025\mathrm{Pr} = 0.025 exige ν≤0.0125\nu \le 0.0125, o sea τf≤0.5375\tau_f \le 0.5375. Un Pr\mathrm{Pr} alto choca con una pared de estabilidad cuando τg→0.5\tau_g \to 0.5. Un Pr\mathrm{Pr} bajo choca con una pared de precisión cuando τg\tau_g crece.

En qué libro contable entra el calentamiento viscoso#

Separar ff de gg genera un problema nuevo. La ecuación de la energía contiene el término de disipación viscosa u⋅(∇⋅Π)\boldsymbol{u} \cdot (\nabla \cdot \boldsymbol{\Pi}). Pero Π\boldsymbol{\Pi} es una cantidad que sale del no equilibrio de primer orden de ff y relaja con τf\tau_f.

Π(1)=−2ρ cs2(τf−Δt2)S\boldsymbol{\Pi}^{(1)} = -2\rho\, c_s^{2}\left(\tau_f - \frac{\Delta t}{2}\right) \boldsymbol{S}

S\boldsymbol{S} es el tensor de velocidad de deformación. Como gg relaja con τg\tau_g, el término de disipación que devuelve el desarrollo de gg lleva τg\tau_g delante. En cuanto los dos tiempos de relajación difieren, los coeficientes dejan de coincidir. Solo cuadran solos cuando Pr=1\mathrm{Pr} = 1. Esa es la razón por la que los DDF acoplados agregan un término de corrección más a la ecuación de gg.

Para calcular esa corrección de forma local en cada nodo hay que cerrar Π(1)\boldsymbol{\Pi}^{(1)} en términos de momentos. La aproximación de 13 momentos de Grad llena ese lugar.

fi≃wi[ρ+ρ ei⋅ucs2+(eiei−cs2I):(ρuu+Π(1))2cs4]f_i \simeq w_i\left[\rho + \frac{\rho\, \boldsymbol{e}_i \cdot \boldsymbol{u}}{c_s^{2}} + \frac{(\boldsymbol{e}_i \boldsymbol{e}_i - c_s^{2}\boldsymbol{I}) : \left(\rho \boldsymbol{u}\boldsymbol{u} + \boldsymbol{\Pi}^{(1)}\right)}{2 c_s^{4}}\right]

Con Π(1)=0\boldsymbol{\Pi}^{(1)} = 0 reaparece intacta la distribución de equilibrio de siempre. Cuando τf≠τg\tau_f \ne \tau_g, el calentamiento viscoso queda encerrado en Pr=1\mathrm{Pr}=1, y lo retoma el cuasi-equilibrio del LB de dos poblaciones. La aproximación de Grad lleva ese desarrollo un orden más allá y devuelve el esfuerzo de no equilibrio al interior de la función de distribución. Ahí también se bifurcan los DDF acoplados de 2007 (el modelo de Li y colaboradores para Navier–Stokes compresible) y los modelos desacoplados de bajo Mach. Los primeros agregan la corrección de forma explícita; los segundos descartan por completo el calentamiento viscoso.

Cuánta física aguanta una sola función de distribución#

Con una sola ff caben ρ\rho, u\boldsymbol{u} y un tiempo de relajación: ahí termina el presupuesto. En cuanto la temperatura se monta sobre el segundo momento de esa misma ff, Pr\mathrm{Pr} y γ\gamma dejan de ser propiedades del fluido y pasan a ser constantes de la retícula. En cálculos Boussinesq de bajo Mach el problema no aparece, porque allí la temperatura es de todas formas un escalar pasivo. Al pasar a flujo térmico compresible, las dos constantes se cobran juntas.

En un código de LBM térmico heredado basta con buscar primero tres líneas. Si la temperatura sale de un momento de ff o de un arreglo aparte. Si γ\gamma está fijado a mano como constante o se calcula desde D+n0D + n_0. Y si junto al término de colisión de gg hay una corrección que use Π(1)\boldsymbol{\Pi}^{(1)}. Si falta la tercera y además τf≠τg\tau_f \ne \tau_g, el calentamiento viscoso de ese código es un valor que nunca se calculó.

Comparte si te resultó útil.