Improvements to a semi-implicit integration scheme for viscous fluids in SPH

Why

Low Reynolds number \Longrightarrow small timestep

Standard WCSPH with explicit integrator:

Δtminβ{C1haβ,C2hcβ,C3ρβh2μβ} \Delta t \le \min_\beta \left\{ C_1\sqrt{\frac{h}{\lVert\vec a_\beta\rVert}}, C_2\frac{h}{c_\beta}, C_3\frac{\rho_\beta h^2}{\mu_\beta} \right\}

hh smoothing length, cc sound speed, a\vec a acceleration, ρ\rho density and μ\mu dynamic viscosity

High viscosity + moderate/high resolution \Longrightarrow very small Δt\Delta t.

(For sound speed we cheat with c=10umaxc = 10 u_{max},
can’t do that with viscosity in viscous flows!)

Implicit integration to the rescue

Avoid viscous constraint on time-step with semi-implicit integration (Zago et al., 2018 doi:10.1016/j.jcp.2018.07.060):

uβ(n+1)=uβ(n)+Δt(fβ,P(n)+g)+Δtα2μαβ(n)ρα(n)ρβ(n)Fαβ(n)mαuαβ(n+1) \vec u_\beta^{(n+1)} = \vec u_\beta^{(n)} + \Delta t \left(\vec f_{\beta,P}^{(n)} + \vec g\right) + \Delta t \sum_\alpha \frac{2\bar\mu_{\alpha\beta}^{(n)}}{\rho_\alpha^{(n)} \rho_\beta^{(n)}} F^{(n)}_{\alpha\beta} m_\alpha \vec u_{\alpha\beta}^{(n+1)}

uu velocity, FF scalar part of W\nabla W, fP\vec f_P pressure forces, ()\cdot^{(\cdot)} step of evaluation.

Rearrange and get A(n)(Δt)u(n+1)=b(n)(Δt) A^{(n)}(\Delta t) \vec u^{(n+1)} = \vec b^{(n)}(\Delta t)

b\vec b is just inviscid integration

Simple case

Fluid part of matrix A(n)A^{(n)} is always diagonally dominant.
Also symmetric if single-fluid system had uniform initialization.

Boundary? Depends on BC!

Dynamic BC \Longrightarrow boundary particle velocity is known \Longrightarrow matrix is SPD \Longrightarrow solve with Conjugate Gradient.

(But let’s be honest here, there’s better BCs.)

What

Other boundary conditions?

Consider e.g. “dummy” boundary conditions (Adami et al.).

Viscous contribution from boundary 𝒲\mathcal W to fluid \mathcal F particles uses fictitious velocity

uβ,v=2uβ,wαuαWβααWβα \vec u_{\beta,v} = 2 \vec u_{\beta,w} - \frac{ \sum_{\alpha\in\mathcal F} \vec u_\alpha W_{\beta\alpha} }{ \sum_{\alpha\in\mathcal F} W_{\beta\alpha} }

uw\vec u_w prescribed wall velocity

Implicit visc. scheme \Longrightarrow must compute uv\vec u_v for 𝒲\mathcal W and u\vec u for \mathcal F together.

Matrix shape

Diagonal: Off-diagonal
Aββ(n)(Δt)={1Δtα𝒲Kαβ(n)β,1β𝒲 A_{\beta\beta}^{(n)}(\Delta t) = \begin{cases} 1 - \Delta t \displaystyle\sum_{\alpha\in\mathcal F \cup \mathcal W} K_{\alpha\beta}^{(n)} &\forall\beta\in\mathcal F,\\ 1 & \forall\beta\in\mathcal W \end{cases} Aβα(n)(Δt)={ΔtKαβ(n)β, neib α𝒲WβααWβαβ𝒲, neib α0otherwise A_{\beta\alpha}^{(n)}(\Delta t) = \begin{cases} \Delta t K_{\alpha\beta}^{(n)} & \text{$\beta\in\mathcal F$, neib $\alpha \in\mathcal F\cup\mathcal W$}\\ \frac{W_{\beta\alpha}}{\displaystyle\sum_{\alpha'\in\mathcal F} W_{\beta\alpha'}} & \text{$\beta\in\mathcal W$, neib $\alpha\in\mathcal F$}\\ 0 & \text{otherwise} \end{cases}

with Kαβ(n)=2μαβ(n)ρα(n)ρβ(n)Fαβ(n)mαK_{\alpha\beta}^{(n)} = -\frac{2\bar\mu_{\alpha\beta}^{(n)}}{\rho_\alpha^{(n)} \rho_\beta^{(n)}} F_{\alpha\beta}^{(n)} m_\alpha

Fluid rows still diagonally dominant: |Aββ|=1+αβ|Aβα|\lvert A_{\beta\beta}\rvert = 1 + \sum_{\alpha \ne \beta} \lvert A_{\beta\alpha}\rvert,
boundary rows not (|Aββ|=αβ|Aβα|\lvert A_{\beta\beta}\rvert = \sum_{\alpha \ne \beta} \lvert A_{\beta\alpha}\rvert)!

Matrix is Weakly-Chained Diagonally Dominant (chain: single link from 𝒲\mathcal W to contributing \mathcal F) \Longrightarrow non-singular.

Can still solve (?)

Matrix is non-singular, but also not symmetric.
Let’s solve A(n)(Δt)u(n+1)=b(n)(Δt)A^{(n)}(\Delta t) \vec u^{(n+1)} = \vec b^{(n)}(\Delta t) using BiCGSTAB.

In single precision.

With residue tolerance εtolb\varepsilon_{tol} \lVert \vec b\rVert.

And εtol=εM\varepsilon_{tol} = \varepsilon_M single-precision machine epsilon.

(Narrator voice: they couldn’t)

BiCGSTAB numerical stability

BiCGSTAB not STAB enough?
Can’t work with such strict tolerances in single precision
(algorithm stalls or blows up).

(Everybody knows that: it’s why they use εtol=105\varepsilon_{tol} = 10^{-5}.)

But why go the easy way when you can suffer?

Let’s fix BiCGSTAB instead.

How

Standard BiCGSTAB

x0\vec x_0 initial guess, r0=bAx0\vec r_0 = \vec b - A\vec x_0 residual, r̂0=r0\hat{\vec r}_0 = \vec r_0, p0=0\vec p_0 = \vec 0, γ0=α0=ω0=1\gamma_0 = \alpha_0 = \omega_0 = 1. Iterate:

γi=r̂0ri1\gamma_i = \hat{\vec r}_0 \cdot \vec r_{i-1}
βi=γiγi1αi1ωi1\beta_i = \frac{\gamma_i}{\gamma_{i-1}} \frac{\alpha_{i-1}}{\omega_{i-1}}
pi=ri1+βi(pi1ωi1Api1)\vec p_i = \vec r_{i-1} + \beta_i\left( \vec p_{i-1} - \omega_{i-1} A \vec p_{i-1} \right)
δi=r̂0Api\delta_i = \hat{\vec r}_0 \cdot A \vec p_i
αi=γiδi\alpha_i = \frac{\gamma_i}{\delta_i}
r=ri1αiApi\vec r_\star = \vec r_{i-1} - \alpha_i A \vec p_i
x=xi1+αipi\vec x_\star = \vec x_{i-1} + \alpha_i \vec p_i
ωi=rAr(Ar)(Ar)\omega_i = \frac{\vec r_\star \cdot A \vec r_\star}{(A \vec r_\star)\cdot(A \vec r_\star)}
ri=rωiAr\vec r_i = \vec r_\star - \omega_i A \vec r_\star
xi=x+ωir\vec x_i = \vec x_\star + \omega_i \vec r_\star

(new ⇒)

Improving BiCGSTAB/I

x0\vec x_0 initial guess, r0=bAx0\vec r_0 = \vec b - A\vec x_0 residual, r̂0=r0\hat{\vec r}_0 = \vec r_0, p0=0\vec p_0 = \vec 0, γ0=α0=ω0=1\gamma_0 = \alpha_0 = \omega_0 = 1. Iterate:

γi=r̂0ri1\gamma_i = \hat{\vec r}_0 \cdot \vec r_{i-1}
βi=γiγi1αi1ωi1\beta_i = \frac{\gamma_i}{\gamma_{i-1}} \frac{\alpha_{i-1}}{\omega_{i-1}}
pi=ri1+βi(pi1ωi1Api1)\vec p_i = \vec r_{i-1} + \beta_i\left( \vec p_{i-1} - \omega_{i-1} A \vec p_{i-1} \right) \Longleftarrow start from here
δi=r̂0Api\delta_i = \hat{\vec r}_0 \cdot A \vec p_i
αi=γiδi\alpha_i = \frac{\gamma_i}{\delta_i}
r=ri1αiApi\vec r_\star = \vec r_{i-1} - \alpha_i A \vec p_i
x=xi1+αipi\vec x_\star = \vec x_{i-1} + \alpha_i \vec p_i
ωi=rAr(Ar)(Ar)\omega_i = \frac{\vec r_\star \cdot A \vec r_\star}{(A \vec r_\star)\cdot(A \vec r_\star)}
ri=rωiAr\vec r_i = \vec r_\star - \omega_i A \vec r_\star
xi=x+ωir\vec x_i = \vec x_\star + \omega_i \vec r_\star

Improving BiCGSTAB/II

Expand and simplify! Consider: pi=ri1+βi(pi1ωi1Api1)=ri1+βipi1βiωi1Api1\vec p_i = \vec r_{i-1} + \beta_i \left( \vec p_{i-1} - \omega_{i-1} A \vec p_{i-1} \right) = \vec r_{i-1} + \beta_i \vec p_{i-1} - \beta_i \omega_{i-1} A \vec p_{i-1} and βi=γiγi1αi1ωi1=γiγi1γi1δi1ωi1=γiδi1ωi1=αi1ωi1 \beta_i = \frac{\gamma_i}{\gamma_{i-1}} \frac{\alpha_{i-1}}{\omega_{i-1}} = \frac{\gamma_i}{\gamma_{i-1}} \frac{\gamma_{i-1}}{\delta_{i-1}\omega_{i-1}} = \frac{\gamma_i}{\delta_{i-1}\omega_{i-1}} = \frac{\alpha'_{i-1}}{\omega_{i-1}} where αi1=γiδi1 \alpha'_{i-1} = \frac{\gamma_i}{\delta_{i-1}} so pi=ri1+βipi1αi1Api1\vec p_i = \vec r_{i-1} + \beta_i \vec p_{i-1} - \alpha'_{i-1} A \vec p_{i-1}

Modified BiCGSTAB

x0,r0=bAx0,r̂0=r0\vec x_0, \vec r_0 = \vec b - \vec A\vec x_0, \hat{\vec r}_0 = \vec r_0 as before, p0\vec p_0 don’t care γ0=r̂0r0,α0=β0=0\gamma_0 = \hat{\vec r}_0 \cdot \vec r_0, \alpha'_0 = \beta_0 = 0. Iterate:

pi=ri1+βi1pi1αi1Api1\vec p_i = \vec r_{i-1} + \beta_{i-1} \vec p_{i-1} - \alpha'_{i-1} A \vec p_{i-1}
δi=r̂0Api\delta_i = \hat{\vec r}_0 \cdot A \vec p_i
αi=γiδi\alpha_i = \frac{\gamma_i}{\delta_i}
r=ri1αiApi\vec r_\star = \vec r_{i-1} - \alpha_i A \vec p_i
x=xi1+αipi\vec x_\star = \vec x_{i-1} + \alpha_i \vec p_i
ωi=rAr(Ar)(Ar)\omega_i = \frac{\vec r_\star \cdot A \vec r_\star}{(A \vec r_\star)\cdot(A \vec r_\star)}
ri=rωiAr\vec r_i = \vec r_\star - \omega_i A \vec r_\star
xi=x+ωir\vec x_i = \vec x_\star + \omega_i \vec r_\star
γi+1=r̂0ri\gamma_{i+1} = \hat{\vec r}_0 \cdot \vec r_i
αi=γi+1δi\alpha'_i = \frac{\gamma_{i+1}}{\delta_i}
βi=αiωi\beta_i = \frac{\alpha'_i}{\omega_i}

(⇐ old)

Results

Non-Newtonian Poiseuille

Poiseuille w/ Bingham rheology (Papanastasiou regularization),
semi-implicit predictor/corrector,
convergence/performance results

Performance

Δp\Delta p Δtc\Delta t_c Δtν\Delta t_\nu Explicit RT Implicit RT Speed-up
1/161/16 3.851033.85\cdot10^{-3} 6.551056.55\cdot10^{-5} 3.11023.1\cdot10^2 9.51019.5\cdot10^1 3.3×3.3\times
1/321/32 1.931031.93\cdot10^{-3} 1.641051.64\cdot10^{-5} 4.91034.9\cdot10^3 1.41031.4\cdot10^3 3.5×3.5\times
1/641/64 9.631049.63\cdot10^{-4} 4.091064.09\cdot10^{-6} 1.31051.3\cdot10^5 2.71042.7\cdot10^4 4.8×4.8\times

Longer per-step runtimes (14/21/32 solver iterations on avg),
semi-implicit still wins b.c. timesteps differ by orders of magnitude.

Multi-GPU scaling

Implementation is multi-GPU-capable (easier with reworked BiCGSTAB).
Good strong scaling (w/ enough particles), weak scaling could be improved
(need computation/data exchange overlap).

Thanks