为什么我的水会爆炸?
Why does my water explode?
我正在尝试在 JavaScript 中实现用于模拟流体的 Clavet method,所以调试是一场噩梦,这就是我在这里问的原因,希望有过同样经历的人事情会告诉我我做错了什么。
到目前为止我还可以正常工作:
但是我有两个问题:
1) 由于在这种方法中一切都是 "offset" 半步,我不确定如何正确地将粒子弹离墙壁。现在我获取粒子的位置和之前的位置并围绕交叉墙翻转它们,然后通过反弹因子围绕交叉点缩放。
我的逻辑告诉我这应该可行。算法的下一步是更新粒子速度,所以我也反映了之前的位置。但实际上这给了我一个我不明白的结果:
这显示了粒子上的"forces"。墙壁反射了太多的力量,这让一切都在永恒的运动中。
this paper 中的公式 4.58 显然显示了一种防止这种情况发生的方法,但我无法让它发挥作用。
论文中还有一些我不明白的东西,比如 "we only want to reflect the velocity that was omitted in the collision" 的意思。为什么?有人可以 ELI5 这个东西给我吗?
2) 即使不涉及墙壁,模拟也会定期 "explodes"。这种情况在更高的压力下发生得更多:
这个是JavaScript,所以还有那个,但是我把代码都看了一遍,没有分割零或我可以想象 NaN 发生的情况。
我在报纸上看到一些关于 sim 不稳定性的讨论,我想知道是不是就是这样。这些文献中的大部分内容都超出了我的理解范围。
根据我的理解(我认为),消除不稳定性的方法之一是粘度,但我添加了它但对爆炸没有帮助:
我可以 post 编码,但在开始工作阶段,现在有点难以阅读。
最后一个问题:如何弄清楚如何将此方法中的伪常量转换为物理单位?
编辑:我发现 sim 卡偶尔会死机,似乎它确实在某处产生了 NaN,但 Chrome 发现它已经太晚了。
显然这里有很多。我确定我无法回答所有问题,但这里有一些重要的要点:
关于墙:您实现的内容称为 momentum mirror。在压力下的流体中,动量镜用于吸引具有负表面张力的粒子(因为没有粒子超越它来排斥边界附近的粒子)。那里堆积得越紧密的粒子会产生越大的力,并且更有可能引起数值问题(特别是因为它们的隐形传态往往会赋予它们势能)。
关于恢复系数:碰撞周围的简单线性缩放会产生切向力,这对于动量镜来说并不典型,但确实会产生物理上逼真的防滑条件。
关于您链接的第二篇论文:我认为他们正在尝试根据他们的点投影做一些智能的事情。但是,我不知道为什么它们只是投射回表面(而不是计算碰撞时间,然后根据之后的(降低的)新速度计算新位置)。
假设这是一个没有严格物理意义的 cg 项目...
首先,您真的应该考虑为您的模拟代码使用固定的时间步长,否则您会因为 dt(和错误)抖动而出现不稳定(和视觉上令人不安的)行为。
如果你不能按照你的最终要求获得一致的帧率,位置应该被插值而不是在非固定时间点模拟。
关于你的墙体计算,显然要看你最终想要达到的效果;所以,如果你应用或多或少的动量保持镜像条件(就像你现在所做的那样)
即使应用了阻尼,粒子也会继续 'circulating'。如果你想让流体以某种方式 'stick' 到达墙壁,你需要引入壁力或其他一些更强的耗散效应。
我 运行 你的代码,在设置一致的 dt 和调整粘度并将壁计算简化为更简单的 "if (p.px < left) p.px = left + (left - p.px)*canvas.wallBounce; else if()..." 条件后,我得到了一个很好的
'relaxation' 行为(如果这是您要寻找的)。更新之前的位置也会适得其反,因为它会增加墙 'reflectiveness' 可以这么说。
我正在尝试在 JavaScript 中实现用于模拟流体的 Clavet method,所以调试是一场噩梦,这就是我在这里问的原因,希望有过同样经历的人事情会告诉我我做错了什么。
到目前为止我还可以正常工作:
但是我有两个问题:
1) 由于在这种方法中一切都是 "offset" 半步,我不确定如何正确地将粒子弹离墙壁。现在我获取粒子的位置和之前的位置并围绕交叉墙翻转它们,然后通过反弹因子围绕交叉点缩放。
我的逻辑告诉我这应该可行。算法的下一步是更新粒子速度,所以我也反映了之前的位置。但实际上这给了我一个我不明白的结果:
这显示了粒子上的"forces"。墙壁反射了太多的力量,这让一切都在永恒的运动中。
this paper 中的公式 4.58 显然显示了一种防止这种情况发生的方法,但我无法让它发挥作用。
论文中还有一些我不明白的东西,比如 "we only want to reflect the velocity that was omitted in the collision" 的意思。为什么?有人可以 ELI5 这个东西给我吗?
2) 即使不涉及墙壁,模拟也会定期 "explodes"。这种情况在更高的压力下发生得更多:
这个是JavaScript,所以还有那个,但是我把代码都看了一遍,没有分割零或我可以想象 NaN 发生的情况。
我在报纸上看到一些关于 sim 不稳定性的讨论,我想知道是不是就是这样。这些文献中的大部分内容都超出了我的理解范围。
根据我的理解(我认为),消除不稳定性的方法之一是粘度,但我添加了它但对爆炸没有帮助:
我可以 post 编码,但在开始工作阶段,现在有点难以阅读。
最后一个问题:如何弄清楚如何将此方法中的伪常量转换为物理单位?
编辑:我发现 sim 卡偶尔会死机,似乎它确实在某处产生了 NaN,但 Chrome 发现它已经太晚了。
显然这里有很多。我确定我无法回答所有问题,但这里有一些重要的要点:
关于墙:您实现的内容称为 momentum mirror。在压力下的流体中,动量镜用于吸引具有负表面张力的粒子(因为没有粒子超越它来排斥边界附近的粒子)。那里堆积得越紧密的粒子会产生越大的力,并且更有可能引起数值问题(特别是因为它们的隐形传态往往会赋予它们势能)。
关于恢复系数:碰撞周围的简单线性缩放会产生切向力,这对于动量镜来说并不典型,但确实会产生物理上逼真的防滑条件。
关于您链接的第二篇论文:我认为他们正在尝试根据他们的点投影做一些智能的事情。但是,我不知道为什么它们只是投射回表面(而不是计算碰撞时间,然后根据之后的(降低的)新速度计算新位置)。
假设这是一个没有严格物理意义的 cg 项目...
首先,您真的应该考虑为您的模拟代码使用固定的时间步长,否则您会因为 dt(和错误)抖动而出现不稳定(和视觉上令人不安的)行为。 如果你不能按照你的最终要求获得一致的帧率,位置应该被插值而不是在非固定时间点模拟。
关于你的墙体计算,显然要看你最终想要达到的效果;所以,如果你应用或多或少的动量保持镜像条件(就像你现在所做的那样) 即使应用了阻尼,粒子也会继续 'circulating'。如果你想让流体以某种方式 'stick' 到达墙壁,你需要引入壁力或其他一些更强的耗散效应。
我 运行 你的代码,在设置一致的 dt 和调整粘度并将壁计算简化为更简单的 "if (p.px < left) p.px = left + (left - p.px)*canvas.wallBounce; else if()..." 条件后,我得到了一个很好的 'relaxation' 行为(如果这是您要寻找的)。更新之前的位置也会适得其反,因为它会增加墙 'reflectiveness' 可以这么说。