科学仿真

光滑粒子流体动力学:无网格拉格朗日方法及其应用

引言

当流体出现自由表面大变形、破碎、飞溅,或者固体发生冲击碎裂时,基于固定网格的欧拉方法需要昂贵的界面追踪,而拉格朗日网格法会遭遇网格缠绕。光滑粒子流体动力学(Smoothed Particle Hydrodynamics, SPH)彻底抛弃网格:计算域由一组携带质量、动量与能量的粒子表示,场量及其导数通过核函数加权平均获得。SPH 由 Lucy、Gingold 与 Monaghan 于 1977 年为天体物理问题(星团碰撞、超新星爆发)创立,如今已成为自由表面流、高速冲击、泥石流、海洋工程晃荡等问题的重要工具。本文梳理 SPH 的核近似理论、守恒形式的离散格式,并用一维 Sod 激波管算例对照精确 Riemann 解做定量验证。

理论基础

核近似与粒子求和

SPH 的第一层近似是核积分插值:任意场量 $f$ 在 $\mathbf{x}$ 处的值用光滑核 $W$(光滑长度 $h$)加权表示,

$$f(\mathbf{x}) \approx \int_\Omega f(\mathbf{x}'), W(\mathbf{x} - \mathbf{x}', h), d\mathbf{x}'$$

核函数需满足归一性 $\int W, d\mathbf{x} = 1$、紧支撑性(多数实用核)与 Delta 极限($h \to 0$ 时退化为 $\delta$ 函数)。第二层近似是把积分替换为对粒子的求和——以 $m_j/\rho_j$ 作为粒子 $j$ 的体积测度:

$$f_i \approx \sum_j \frac{m_j}{\rho_j} f_j, W_{ij}, \qquad \nabla f_i \approx \sum_j \frac{m_j}{\rho_j} f_j, \nabla_i W_{ij}$$

梯度作用在已知核函数上,因此导数计算无需任何网格拓扑。密度可直接由求和式 $\rho_i = \sum_j m_j W_{ij}$ 获得(求和密度法),粒子质量守恒即自动保证总质量守恒。

守恒形式的动量方程与人工粘性

为使线性动量与角动量严格守恒,动量方程采用压力项对称化形式,并加入 Monaghan 人工粘性 $\Pi_{ij}$ 以捕捉激波、抑制穿透振荡:

$$\frac{d\mathbf{v}_i}{dt} = -\sum_j m_j \left( \frac{P_i}{\rho_i^2} + \frac{P_j}{\rho_j^2} + \Pi_{ij} \right) \nabla_i W_{ij}$$

$$\Pi_{ij} = \frac{-\alpha, \bar{c}_{ij}, \mu_{ij} + \beta, \mu_{ij}^2}{\bar{\rho}_{ij}}, \qquad \mu_{ij} = \frac{h, \mathbf{v}_{ij} \cdot \mathbf{r}_{ij}}{|\mathbf{r}_{ij}|^2 + 0.01 h^2} \quad (\text{仅当 } \mathbf{v}_{ij}\cdot\mathbf{r}_{ij} < 0)$$

$\alpha \sim 1$、$\beta \sim 2$ 为常用取值:线性项模拟体粘性、抹平激波,二次项防止高速碰撞时粒子互穿。流体压力由状态方程封闭:气体用理想气体律 $P = (\gamma-1)\rho e$,弱可压液体则用 Tait 方程 $P = B\left[(\rho/\rho_0)^\gamma - 1\right]$,通过人为放小声速把马赫数压到 0.1 以下以兼顾密度波动与显式时间步长。

数值方法与实现

下面的算例是计算流体力学的”试金石”——Sod 激波管:隔膜左侧 $(\rho, P) = (1, 1)$、右侧 $(0.125, 0.1)$,撤去隔膜后同时产生右行激波、接触间断与左行稀疏波。SPH 实现采用均匀布点、质量承载密度间断($m_j = \rho_j \Delta x$)、高斯核与 Monaghan 格式,全对搜索向量化;随后用 Toro 精确 Riemann 解(Newton 迭代求星区压力 $P^*$)做定量对照:

import numpy as np

# ---------------- Sod 激波管:SPH 模拟 ----------------
gamma = 1.4
dx = 0.004                             # 均匀粒子间距,质量承载密度间断
x0 = 0.5                               # 隔膜位置
x = np.arange(-0.4 + dx/2, 1.4, dx)
rho0 = np.where(x < x0, 1.0, 0.125)
P0   = np.where(x < x0, 1.0, 0.1)
m = rho0 * dx
v = np.zeros(len(x))
u = P0 / ((gamma - 1.0) * rho0)
h = 1.5 * dx
alpha, beta = 1.0, 2.0
dt, nsteps = 5.0e-4, 400               # t_end = 0.2

def gaussian_W(dxij, h):
    """一维高斯核 W 及其对 x_i 的导数"""
    q2 = (dxij / h)**2
    W = np.exp(-q2) / (h * np.sqrt(np.pi))
    dW = -2.0 * dxij * np.exp(-q2) / (h**3 * np.sqrt(np.pi))
    return W, dW

E0 = None
for step in range(nsteps):
    dxij = x[:, None] - x[None, :]
    r2 = dxij**2
    W, dW = gaussian_W(dxij, h)
    rho = W @ m                                    # 求和密度
    P = (gamma - 1.0) * rho * u                    # 理想气体状态方程
    c = np.sqrt(gamma * P / rho)                   # 声速
    dv = v[:, None] - v[None, :]
    vr = dv * dxij
    # Monaghan 人工粘性(仅相互接近时启用)
    mu = h * vr / (r2 + 0.01 * h**2)
    cij = 0.5 * (c[:, None] + c[None, :])
    rhoij = 0.5 * (rho[:, None] + rho[None, :])
    Pi = np.where(vr < 0, (-alpha * cij * mu + beta * mu**2) / rhoij, 0.0)
    # 对称化动量与能量方程
    term = P[:, None]/rho[:, None]**2 + P[None, :]/rho[None, :]**2 + Pi
    a = -(term * m[None, :] * dW).sum(axis=1)
    dedt = 0.5 * (term * m[None, :] * dW * dv).sum(axis=1)
    v += a * dt
    u += dedt * dt
    x += v * dt
    E = (m * (u + 0.5 * v**2)).sum()
    if E0 is None:
        E0 = E
rho = gaussian_W(x[:, None] - x[None, :], h)[0] @ m

# ---------------- Toro 精确 Riemann 解(对照) ----------------
def sod_exact(xs, t, x0=0.5, gamma=1.4):
    rhoL, PL, rhoR, PR = 1.0, 1.0, 0.125, 0.1
    cL, cR = np.sqrt(gamma*PL/rhoL), np.sqrt(gamma*PR/rhoR)
    AL, AR = 2/((gamma+1)*rhoL), 2/((gamma+1)*rhoR)
    BL, BR = (gamma-1)/(gamma+1)*PL, (gamma-1)/(gamma+1)*PR
    def f(P, PK, rhoK, cK, AK, BK):
        if P > PK:                               # 激波分支
            r = np.sqrt(AK/(P+BK))
            return (P-PK)*r, r*(1-0.5*(P-PK)/(P+BK))
        pr = P/PK                                # 稀疏波分支
        return (2*cK/(gamma-1)*(pr**((gamma-1)/(2*gamma))-1),
                pr**(-(gamma+1)/(2*gamma))/(rhoK*cK))
    P = 0.5*(PL+PR)
    for _ in range(30):                          # Newton 迭代求 P*
        fL, dL = f(P, PL, rhoL, cL, AL, BL)
        fR, dR = f(P, PR, rhoR, cR, AR, BR)
        P -= (fL+fR)/(dL+dR)
    fL, _ = f(P, PL, rhoL, cL, AL, BL)
    fR, _ = f(P, PR, rhoR, cR, AR, BR)
    us = 0.5*(fR - fL)                           # 接触间断速度
    cLs = cL*(P/PL)**((gamma-1)/(2*gamma))
    rho_sL = rhoL*(P/PL)**(1/gamma)
    rho_sR = rhoR*(P/PR+(gamma-1)/(gamma+1))/((gamma-1)/(gamma+1)*P/PR+1)
    Ss = cR*np.sqrt((gamma+1)/(2*gamma)*P/PR + (gamma-1)/(2*gamma))
    out = np.empty_like(xs)
    for i, xx in enumerate(xs):
        S = (xx - x0)/t
        if S <= -cL:
            out[i] = rhoL
        elif S <= us - cLs:                      # 稀疏波扇内
            out[i] = rhoL*(2/(gamma+1)-(gamma-1)*S/((gamma+1)*cL))**(2/(gamma-1))
        elif S <= us:
            out[i] = rho_sL
        elif S <= Ss:
            out[i] = rho_sR
        else:
            out[i] = rhoR
    return out, P, us

t = nsteps*dt
xs_eval = np.linspace(0.1, 1.0, 181)
rho_ex, Pstar, ustar = sod_exact(xs_eval, t, x0, gamma)
order = np.argsort(x)
rho_sph = np.interp(xs_eval, x[order], rho[order])
rmse = np.sqrt(np.mean((rho_sph - rho_ex)**2))
print(f"P* = {Pstar:.4f}(文献值 0.3031),u* = {ustar:.4f}(文献值 0.9275)")
print(f"t = {t:.1f} 时密度剖面 RMSE(SPH vs 精确解)= {rmse:.4f}")
print(f"总能量相对变化: {(E-E0)/E0:.2e}")

工程案例分析

SPH 的优势场景几乎都是”网格的痛点”。海洋与船舶工程:液舱晃荡、甲板上浪、溃坝洪水的自由表面剧烈翻卷,SPH 无需任何界面捕捉即可再现。高速冲击与爆炸:超高速撞击下材料经历熔融、汽化与碎片云形成,SPH 的拉格朗日粒子天然携带材料历史且无网格畸变。天体物理:星系并合、吸积盘等无边界问题至今仍是 SPH 的传统领地(GADGET 等代码)。核函数的选择直接影响精度与稳定性,常见选项如下:

核函数 支撑域 光滑性 特点
高斯核 全域(截断至 $3h$) $C^\infty$ 精度高、计算量大、缺紧支撑
三次样条(B 样条) $2h$ $C^2$ 工业标准,支撑域小
五次样条 $3h$ $C^4$ 精度更高,邻居更多
Wendland C2/C4 $2h$ $C^2/C^4$ 抑制粒子聚集,稳定性好

本文算例的定量结果:精确 Riemann 解给出星区压力 $P^* = 0.3031$、接触间断速度 $u^* = 0.9275$(与文献值完全一致);$t = 0.2$ 时 SPH 密度剖面与精确解的 RMSE 为 0.031,未扰动区密度保持在 1.000 与 0.125,总能量漂移仅 $9.7\times10^{-4}$——对称化格式的守恒性得到验证。需要清醒认识 SPH 的三个经典短板:一是拉伸失稳(tensile instability),拉伸状态下粒子成团聚拢,可用人工应力或修正核缓解;二是边界处理,固壁附近核支撑被截断导致密度低估,常用镜像粒子、排斥力粒子或半解析边界积分补偿;三是低阶精度,朴素 SPH 不具备线性完备性,CSPM、RKPM 等修正格式可恢复一致性。工程选型上还面临 WCSPH(弱可压,显式但步长小)与 ISPH(不可压,隐式求解压力 Poisson 方程)之争。

结论与展望

本文从核积分插值与粒子求和两层近似出发,建立了 SPH 的守恒形式动量方程与人工粘性激波捕捉机制,并以 Sod 激波管对照精确解完成定量验证。SPH 用”粒子 + 核平均”换取了对大变形、自由表面与碎裂问题的天然适应力,代价是精度、边界与稳定性上的额外技术处理。当前发展方向包括:$\delta$-SPH 等密度耗散修正格式、自适应粒子加密(variable resolution)、SPH-FEM 耦合(流体粒子与结构网格交互),以及 GPU 并行下千万粒子级的工程化应用(DualSPHysics、GPUSPH 等开源代码)。对涉及破碎与飞溅的流动问题,SPH 往往是唯一”开箱即用”的选择。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注