目的:
参考《GPU Gems》,在UE4中尝试重现2D流体模拟。
本节试图结合场论知识粗略理解Navier–Stokes equations。
参考:
观察:
(《花样年华》 梁朝伟)
《GPU Gems》中的Navier–Stokes equations描述了一个流体的4部分运动:
平流项:烟随着速度场向上升
压力项:烟碰到顶灯受到顶部压力,离压力源近的烟分子被碰撞,并将这个压力传播出去。
扩散项:在烟上升的过程中,其分子会扩散,整个烟的形状不会保持不变地向上。
外力项:随意。如手挥过,烟受外力影响变化。
分析:
1.数学前提:
矢量微积分/场论,推荐IEEE成员-梁昌洪老师的公开课。b站上3Blue1Brown也有若干相关视频。
2.《GPU Gems》希望在2维平面进行水流流体模拟。
公式:
方程一:
方程二:
(注意:为方便,改写符号)
其中,u是x,y方向速度矢量场,t是时间,是流体密度(常数),P是压力数值场,k是动力粘度,F是外力。
在二维平面上,方程1可拆解为(x,y)两方向的速度(u1,u2)
方程二告诉我们,模拟的是一个无源场。
在我看来,方程一的核心思想,就是热传导。
方程一分4部分拆解:
平流项:
展开:
也就是说,u1,u2的加速度平流部分为:
注意,这里的速度符号u1,u2和位置符号x,y不能搞混。
对于像我这样的新手,算子的运算规则也要十分小心。
这里处于位置的
算子又被称为平流算子(advection operator)。
那为什么这个方程就是平流呢?什么是平流?
我一开始也被搞糊涂了,直到看到实现的时候这个项的变化。
举个实在例子,设d为染料浓度,在这里我们假设d是一个属于(0,1)的数量场,0为纯白流体,1为黑色染料。水体在流动时,一些染料被跟着带走。那么就有
令d有x,y轴分量场d=d1+d2,则有
我们令速度场不随时间变化。
如果u1还不随x变化,那么u1就是一个常数,此时就是一个标准的一维平流方程(Advecation Equation)。
为了看出此方程对染料干了什么,我还是让u1随空间变化。
我尝试解这个偏微分方程,但失败了,转看wiki:
“The advection equation is not simple to solve numerically: the system is a hyperbolic partial differential equation, and interest typically centers on discontinuous "shock" solutions (which are notoriously difficult for numerical schemes to handle).
Even with one space dimension and a constant velocity field, the system remains difficult to simulate. ”
看来照目前情况咱没能力解方程。
但通过搜索可知,一种解是:
阿,尼马。绕了半天你就为得到这么一个结果,即当前帧的某位置p1浓度就是前一帧的在位置的浓度。
也就是速度场带着浓度平移(流动),看下图一眼便知:
那为什么你这个要用速度场带动速度场呢?这又是个什么玩意呢?你实现里也没有,我也不懂,wdnmd我被搞了。
由此,我们再次体会到平流算子这种叫法的正确性。平流只是连接速度场与被平流场的一个算子。
压力项:
一目了然,向着压力场(数值场)的负梯度方向调整。其压力场概念图类似这样:
扩散项:
。
拉普拉斯算子,是各轴二阶导数之和。离散地来看,二阶导数反应了该点与附近两点相差的平衡。
而加上二阶导数这一行为,从微观上表现了该点试图与周围点保持平衡。
热传导中的拉普拉斯方程就可以这样理解,3B1B在此视频的10分钟讲得很清楚。
像烟雾因为热力学原因要往周围扩散,或者是水流因为其他原因要扩散,用速度场希望“热传导平衡”来模拟,问题也不大。
外力项:
略。
结语
本篇参考《GPU Gems》,对书中采用的Navier–Stokes equations进行了粗略地分析,有了直观上的感受。接下来继续结合理论知识,最终推导出能适用于GPU编程的离散形式。