前言:这个系列是我很早以前写的,这次重新开博原本并不打算重新找回原来的文章,不过不断有朋友找找我要其中的源码和图片,好在这些还有备份,重新发出来以做纪念
SPH(Smoothed Particle Hydrodynamics)算法是一种流体模拟算法,他的特点是简单快速,可以用在例如游戏这样的实时的交互软件中。SPH算法虽然简单,但要完全搞明白其中的原理和实现方法,也不是易事,写这个系列希望能全面介绍一下相关的内容,如果你搜索到这里,可以仔细看一下这个系列,希望能帮到你。
烟雾、海浪、水滴…,这些司空见怪的自然现象其实有着非常复杂的数学规律,对于流体的研究,有两种完全不同的视角,分别是欧拉视角和拉格朗日视角。欧拉视角的坐标系是固定的,如同站在河边观察河水的流动一样,用这种视角分析流体需要建立网格单元,还会涉及到有限元等复杂的工程方法,一般用在离线的应用中。而拉格朗日视角则将流体视为流动的单元,例如将一片羽毛放入风中,那么羽毛的轨迹可以帮我们指示空气的流动规律。
SPH算法是典型的拉格朗日视角,它的基本原理就是通过粒子模拟流体的运动规律,然后再转换成网格进行流体渲染。
> | > |
---|
在正式开始之前,需要把SPH算法涉及到的相关数学概念介绍一下,这些概念基本上都是大学数学中的内容,所以不用紧张,翻翻书就能想起来。
标量场和矢量场
如果空间区域内一点M,都有一个确定的数量f(M),则称这个空间区域内确定了一个标量场,如果空间区域内任意一点M,都有一个确定的向量F(M),则称这空间区域内确定了一个矢量场。例如,液体中的密度,就是标量场,而速度,就是矢量场
偏导数
对于多元函数\(z=f(x,y)\),定义\(z\)在\((x_0,y_0)\)处相对于x的偏导数为
$$
\frac{\partial z}{\partial x}=\lim_{\triangle x\rightarrow 0}\frac{f(x_0+\triangle x, y_0)-f(x_0,y_0)}{\triangle x}\tag{1.1}
$$ 例如,定义\(z=x^2+2xy+y^3\),那么\(\partial z/\partial x=2x+2y,\partial z/\partial y=2x+3y^2\)
哈密顿算子
哈密顿算子\(\nabla\)在流体力学中是如此重要,以至于很多地方将这个符号作为流体力学的标志,所以这里要着重介绍一下,所谓“算子”,就是那种不能单独存在,必须和其他符号放在一起的一种数学符号,例如微分中的那个“d”。哈密顿算子的定义如下:$$
\nabla\equiv\vec{x}\frac{\partial}{\partial x}+\vec{y}\frac{\partial}{\partial y}+\vec{z}\frac{\partial}{\partial z}\tag{1.2}
$$ 哈密顿算子有很多有趣的特性,它本身虽然并不是一个矢量,但很多运算确实可以把它视为一个矢量,例如把它作用在一个标量场\(A=f(x,y,z)\)上,那么$$
\nabla A=\vec{x}\frac{\partial f}{\partial x}+\vec{y}\frac{\partial f}{\partial y}+\vec{z}\frac{\partial f}{\partial z}\tag{1.3}
$$ 这个运算可以视为一个矢量和标量的乘法,得到的\(\nabla A\)是一个矢量场,称为A的“梯度”,顾名思义,梯度的含义就是标量场A在某处变化快慢和方向,比如一个标量场H(x,y)是一座高山在(x,y)处的高度,则H的梯度是该高山在某处陡峭的程度,并且方向指向高处。
而如果把哈密顿算子作用在一个矢量场\(\vec{A}\)上,得到的\(\nabla\cdot\vec{A}\)称为矢量场A的“散度”,散度的计算和矢量的点积运算相似,得到的是一个标量场。$$
\nabla\cdot\vec{A}=\left(\vec{x}\frac{\partial}{\partial x}+\vec{y}\frac{\partial}{\partial y}+\vec{z}\frac{\partial}{\partial z}\right)\cdot(\vec{x}A_x+\vec{y}A_y+\vec{z}A_z)=\frac{\partial A_x}{\partial x}+\frac{\partial A_y}{\partial y}+\frac{\partial A_z}{\partial z}\tag{1.4}
$$ 散度的意义也很明显,就是描述一个矢量场“发散”的程度,例如下面的两个矢量场,左边的有很大的散度,而右边的散度为0
拉普拉辛算子
拉普拉辛算子\(\nabla^2\)是二阶微分算子,有时也可写作\(\triangle\)或者\(\nabla\cdot\nabla\)$$
\nabla^2\equiv\frac{\partial^2}{\partial x^2}+\frac{\partial^2}{\partial y^2}+\frac{\partial^2}{\partial z^2}\tag{1.5}
$$ 例如对于\(A=f(x,y,z)\)
$$
\nabla^2A=\frac{\partial^2A}{\partial x^2}+\frac{\partial^2A}{\partial y^2}+\frac{\partial^2A}{\partial z^2}\tag{1.6}
$$
请问你的网站用了什么模版?图像,公式表现得都很不错。
wordpress和bluefreedom主题,公式是在world里编辑好然后粘到文章里的
你讲的很好,谢谢,我现在也是要用该方法做个模拟,原书后边的程序使用的F77,所以调了好久都没有调通,百度上你给的源代码下载也打不开,请问您能发到我邮箱吗,我想先看看他运行的结果,然后再根据我自己的问题,对其做大量的修改。谢谢
可执行程序和可运行程序的下载链接在这篇文章里: http://thecodeway.com/blog/?p=204
您好按照你的方法实现了一个流体效果。但是这个水流只能在自己定义的长宽高里面流动,对于让水在一个管道里面流动,就好像水在河里从上往下流碰到石头什么的。这种流体和障碍物的处理,请教下您的思路。