我的博客和笔记我的博客和笔记
首页
文章
  • TurboLink
  • TinyEncrypt
  • UnrealStyleGuide
  • AxTrace
  • Cyclone
  • 数学相关
  • 图形学
  • 密码学
  • 编程语言
关于
GitHub
首页
文章
  • TurboLink
  • TinyEncrypt
  • UnrealStyleGuide
  • AxTrace
  • Cyclone
  • 数学相关
  • 图形学
  • 密码学
  • 编程语言
关于
GitHub
  • 我的文章

    • 从抛币协议到智能合约

      • Part1
      • Part2
    • JPEG算法解密

      • Part1
      • Part2
      • Part3
      • Part4
      • Part5
      • Github
    • SPH算法简介

      • Part1
      • Part2
      • Part3
      • Part4
      • Github
    • 赌博中的数学:Martingle策略
    • 如何生成一个随机的圆形
    • 一个简单的DH密钥协商算法的实现
    • 如何计算线段和圆的交点
    • 一道数学趣题
    • 斐波那契数列和1/89
    • 匀速贝塞尔曲线运动的实现

      • Part1
      • Part2
  • 开源项目

    • TurboLink
    • TinyEncrypt
    • UnrealStyleGuide
    • AxTrace
    • Cyclone
  • 学习笔记

    • 数学相关

      • 常用数学符号
      • 群
      • 数论(一)
      • 数论(二)
      • 数论(三)
      • 概率
    • 密码学

      • RSA
      • 抛币协议
      • 智能扑克协议
    • 图形学

      • 数学基础

        • 矢量
        • 矩阵
        • 立体角
        • 几何变换(一)
        • 几何变换(二)
        • 法线变换
        • 摄像机变换
      • 光照模型

        • 传统光照模型
        • 光度学
        • 双向反射分布函数(BRDF)
        • 微平面理论(一)
        • 微平面理论(二)
        • 微平面理论(三)
        • 光照方程
      • 环境光渲染

        • 环境光渲染(一)
        • 环境光渲染(二)
    • 编程语言

      • JavaScript

        • 环境搭建
        • 基本语法
        • 函数
        • 对象和类

和其他流体力学中的数学方法类似,SPH算法同样涉及到“光滑核”的概念,可以这样理解这个概念,粒子的属性都会“扩散”到周围,并且随着距离的增加影响逐渐变小,这种随着距离而衰减的函数被称为“光滑核”函数,最大影响半径为“光滑核半径”。

光滑核函数一般具有的形态

反过来不难理解,尽管我们将流体视为一个个分散的粒子,但流体毕竟是连续充满整个空间的,流体中每个位置参与运算的值都是由周围一组粒子累加起来的。

设想流体中某点r→(此处不一定有粒子),在光滑核半径h范围内有数个粒子,位置分别是r0→,r1→,r2→,…rj→,则该处某项属性A的累加公式为:

(3.1)A(r→)=∑jAjmjρjW(r→−rj→,h)

其中Aj是要累加的某种属性,mj和ρj是周围粒子的质量和密度,r→是该粒子的位置,h是光滑核半径。函数W就是光滑核函数。
光滑核函数两个重要属性,首先一定是偶函数,也就是W(−r)=W(r),第二,是“规整函数”,也就是

∫W(r)dr=1

SPH推导过程

我们假设流体中一个位置为ri→的点,此处的密度为ρ(ri)、压力为p(ri)、速度为u→(ri),那么我们可以根据上一篇的公式2.8,可以推导出此处的加速度a→(ri)为

(3.2)a→(ri)=g→−∇p(ri)ρ(ri)+μ∇2u→(ri)ρ(ri)

对于SPH算法来说,基本流程就是这样,根据光滑核函数逐个推出流体中某点的密度,压力,速度相关的累加函数,进而推导出此处的加速度,从而模拟流体的运动趋势,下面我们逐个来分析


密度

根据公式3.1,用密度ρ代替A,可以得到

(3.3)ρ(ri)=∑jρjmjρjW(ri→−rj→,h)=∑jmjW(ri→−rj→,h)

计算使用的光滑核函数称为Poly6函数,具体形式为:

(3.4)WPoly6 (r→,h)={KPoly6 (h2−r2)3,0≤r≤h0,otherwisewith r=|r→|

其中KPoly6是一个固定的系数,根据光滑核的规整属性,通过积分计算出这个系数的具体值,在2D情况下,在极坐标中计算积分:

(3.5)KPoly6=1/∫02π∫0hr(h2−r2)3dr dθ=4πh8

3D情况下,在球坐标中计算:

(3.6)KPoly6=1/∫02π∫0π∫0hr2sin(φ)(h2−r2)3dr dφ dθ=31564πh9

由于所有粒子的质量相同都是m,所以在3D情况下,ri→处的密度计算公式最终为:

(3.7)ρ(ri)=m31564πh9∑j(h2−|ri→−rj→|2)3

压力

根据上一节的结论,在位置ri之处的由压力产生的作用力的计算公式为

(3.8)Fi→pressure=−∇p(ri→)=−∑jpjmjρj∇W(ri→−rj→,h)

不过不幸的是,这个公式是“不平衡”的,也就是说,位于不同压强区的两个粒子之间的作用力不等,所以计算中一般使用双方粒子压强的算术平均值代替单个粒子的压力ri之处的由压力产生的作用力的计算公式为

(3.9)Fi→pressure=−∑jmj(pi+pj)2ρj∇W(ri→−rj→,h)

对于单个粒子产生的压力p,可以用理想气体状态方程计算

(3.10)p=K(ρ−ρ0)

其中ρ0是流体的静态密度,K是和流体相关的常数,只跟温度相关。
压力计算中使用的光滑核函数称为Spiky函数

(3.11)WSpiky(r→,h)={KSpiky (h−r)3,0≤r≤h0,otherwisewith r=|r→|

在3D情况下,KSpiky=15/(πh6)

(3.12)∇WSpiky (r→,h)=15πh6∇(h−r)3=−r→45πh6r(h−r)2

将公式3.12带入3.9,可以整理出公式3.2中压力产生的加速度部分

(3.13)ai→pressure=−∇p(ri→)ρi=m45πh6∑j(pi+pj2ρiρj(h−r)2ri→−rj→r)with r=|ri→−rj→|

粘度

现在把注意力集中到公式3.2中最后一部分,由粘度产生的作用力

(3.14)Fi→viscosity=μ∇2u→(ri)=μ∑juj→mjρj∇2W(ri→−rj→,h)

这个公式同样有不平衡的问题,考虑到公式中的速度其实并不是绝对速度,而是粒子间的相对速度,所以正确写法应该是:

(3.15)Fi→viscosity=μ∑jmjuj→−ui→ρj∇2W(ri→−rj→,h)

其中的光滑核函数形式如下:

(3.16)Wviscosity (r→,h)={Kviscosity (−r32h3+r2h2+h2r−1),0≤r≤h0,otherwisewith r=|r→|

在3D情况下,Kviscosity=15/(2πh3)

(3.17)∇2Wviscosity (r→,h)=∇2152πh3(−r32h3+r2h2+h2r−1)=45πh6(h−r)

由此可得到公式3.2的粘度部分

(3.18)ai→viscosity=Fi→viscosityρi=mμ45πh6∑juj→−ui→ρiρj(h−∣ri→−rj→∣)

把公式3.13和3.17带入3.2,可以得到,对于粒子i,它的加速度可以由下面的公式计算

(3.19)a→(ri)=g→+m45πh6∑j(pi+pj2ρiρj(h−r)2ri→−rj→r)+mμ45πh6∑juj→−ui→ρiρj(h−r)with r=|ri→−rj→|

好了,我们似乎推导出一大推复杂的公式,不用担心,你已经过了最困难的部分,下一节我们来点真的,让这些公式运行起来看看

Prev
Part2
Next
Part4