为什么我的水会爆炸?

25
我正在尝试在JavaScript中实现Clavet方法来模拟流体,因此调试非常困难,这就是为什么我在这里提问的原因,希望有人能告诉我我做错了什么。
到目前为止,我的工作还算可以:

particles basically work

但我有两个问题:

1)由于在这种方法中一切都被“偏移”了半步,我不确定如何正确地将粒子从墙上弹回。目前,我取粒子的位置和先前的位置,并将它们在穿过的墙壁周围翻转,然后以一个反弹系数在穿越点周围进行缩放。

my reflection method

我的逻辑告诉我这应该是可行的。算法的下一步是更新粒子速度,所以我也反射了先前的位置。但实际操作中,这给了我一个我不理解的结果:

too much reflected force

这显示了粒子所受的“力”。墙壁反射的力过大,使得一切都处于永久运动中。 这篇论文 中的公式4.58似乎可以解决这个问题,但我一直没有成功地让它起作用。
此外,论文中还有一些我不理解的东西,比如“我们只想反射在碰撞中被省略的速度”是什么意思。为什么?能有人向我解释得简单明了点吗?
2)即使没有涉及到墙壁,模拟也会定期“爆炸”。这种情况在压力更高时发生得更多。

exploding sim

这是JavaScript代码,所以有那个,但我已经检查了代码,没有除以零或者我能想象出NaN的情况。
我看到报纸上有些关于模拟不稳定性的讨论,我想知道这是否就是原因。大部分文献都超出了我的理解范围。
从我所理解的(我认为),消除不稳定性的方法之一是黏度,但我添加了它,并没有帮助避免爆炸。

viscosity doesn't prevent explosions

我可以发布代码,但在“让它先正常运行”阶段,现在阅读起来有些困难。

最后一个问题:我如何确定如何从此方法中的伪常量转换为物理单位?

编辑:我发现模拟有时会冻结,似乎确实在某个地方产生了NaN,但Chrome追踪得太晚了。


以你的代码为灵感,与其他人分享一个要点,我们会深入探讨。https://gist.github.com/ - Scott Stensland
我警告过你,以下内容涉及编程。https://gist.github.com/alexbourt/ca5b9e44f6ecbfcc6b8a52d805caa9f6 - Alex
2
永动万物”这不就是现实生活吗?我认为为了获得稳定性,需要通过减震来将运动降至零一旦达到某个最小值。虽然这是一个非常有趣的演示,但我认为它与本主题无关。如果您有特定的编程问题,那很好。但这似乎更多地涉及流体动力学算法。 - RobG
抱歉,我尝试在计算机图形论坛中提问,但是我在那里没有足够的声望来添加所有图片。 :( 或许管理员可以将这个问题移动到那里? - Alex
1
我很有兴趣尝试找出问题所在,但我想运行您的模拟,而不仅仅是阅读它。您发布的代码没有初始化自身,并且至少缺少一个函数getAngle。您能否发布一个完整的示例,可以将其粘贴到.html文件中并在浏览器中运行?(即使将其放在问题末尾的代码块中也可以。) - s4y
我的当前进展在http://bourt.com/particles.html。我添加了控件来调整参数。将比例设置为1,然后开始操作。此外,鼠标左键移动粒子,Ctrl+Shift+鼠标左键添加一些粒子。(尽管我还没有实现答案中的任何建议,因为我不在场。) - Alex
2个回答

3
显然这里有很多内容。我相信我不能回答所有问题,但以下是一些重要的要点:
关于墙壁:您实现的被称为动量镜像。在受压的流体中,动量镜像会吸引粒子,具有一种负表面张力(因为没有粒子在其外部来排斥接近边界的粒子)。更加紧密地堆积的粒子将产生更大的力,并更有可能引起数值问题(特别是因为它们的传送往往会赋予它们势能)。
关于恢复系数:在碰撞时的简单线性缩放会产生切向力,这不是动量镜像通常具有的特征,但会产生物理上真实的无滑移条件。
关于你提供的第二篇论文:我认为他们正在尝试基于点投影做一些智能的事情。然而,我不知道为什么他们仅仅投回到表面(而不是计算碰撞时间,然后根据(减少的)新速度在此之后计算新位置)。

3

假设这是一个没有严格物理意义的计算机图形学项目...

首先,你应该考虑在你的模拟代码中使用固定时间步长,否则dt和误差会发生抖动,产生不稳定(和视觉上令人不适的)行为。 如果无法按照最终要求获得一致的帧率,则应该在非固定时间点插值而不是模拟位置。

关于墙壁计算,这显然取决于您最终想要实现的效果;因此,如果您应用了一个更或多或少保持动量的镜像条件(如您现在所做的),那么颗粒即使施加阻尼也将继续“循环”。如果您希望流体以某种方式“粘附”于墙壁,则需要引入墙壁力或其他更强的耗散效应。

我运行了你的代码,在设置了一致的dt并调整黏度和简化墙壁计算为更简单的"if (p.px < left) p.px = left + (left - p.px)*canvas.wallBounce; else if()..."条件后,我得到了一个不错的“松弛”行为(如果这是你要寻找的)。同样更新前一个位置是适得其反的,因为它会增加墙的“反射率”,可以说。


抱歉问一些愚蠢的问题,我在这方面没有正式的教育,显然。 :) 我是否正确理解,现在我弹起粒子的方式,所有水的集体重量都会反射回来,这就是为什么底部粒子如此充满活力的原因?如果是这样,那在现实生活中不也是这样吗? - Alex
如果你所说的“充满活力”是指为什么在模拟中粒子在墙附近出现更加紧密和快速,我认为原因有两个:首先,正如Davis Herring所指出的那样,负表面张力会增加它们在壁边界处的数密度,从而排斥体积内的粒子(这就是为什么你看到了一个在壁边界处的“间隙”);其次,如上所述,除非你添加墙面力,否则粒子将倾向于保持它们的能量/动量,导致一种始终“旋转”的流体外观...这进一步加剧了由于时间步长抖动和数字误差所导致的问题。 - Massimiliano Janes
关于现实生活中发生的事情,这并不是一个琐碎的问题,甚至决定什么是“流体元素”真正需要对该主题有非琐碎的知识(流体元素不是流体微观组成部分,如分子等...)。无论如何,真实的流体(超流体除外)将在“零”距离处粘附在墙上(然后要么进入静止层流运动,要么进入分离流后跟随湍流运动)... - Massimiliano Janes
在平衡状态下,您在边界粒子上观察到的唯一额外能量应该是表面张力和(向地面增加的)由于重力引起的静水压力...(当然忽略热量等因素)。 - Massimiliano Janes
我在这个主题中实施了所有的建议,到目前为止我有了这个:http://bourt.com/particles.html。如果我减小时间步长或者休息密度,我可以使疯狂跳舞的力量消失,但是这不应该是一个如此大量粒子的问题...我错过了什么?这是休息密度与单元格大小的问题吗?并且,在数学上,将热(或类似热的东西)添加到其中最简单的方法是什么? - Alex
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接