4

我有一个简单的程序,它的核心是一个二维浮点数组,据说代表气体浓度,我一直试图想出一个简单的算法来模拟向外膨胀的气体,就像一朵云,最终得到电网各处的气体浓度相同。

例如,给定的状态进程可能是:(为简单起见,使用整数)

起始状态

00000
00000
00900
00000
00000

1 次算法通过后的状态

00000
01110
01110
01110
00000

再过一次应该给出一个 5x5 的网格,所有网格都包含 0.36 (9/25) 的值。
我已经在纸上进行了尝试,但无论我如何尝试,我都无法理解算法来做到这一点。

所以我的问题是,我应该如何着手编写这个算法?我已经尝试了一些方法,应用卷积,尝试依次获取每个网格单元并将其分配给它的邻居,但它们最终都会产生不良影响,例如最终使用的气体比我最初开始时少,或者所有的气体运动都在一个方向上,而不是从中心向外扩展。我真的完全无法理解它,并且非常感谢任何帮助。

4

7 回答 7

6

如果你忽略对流,要么是扩散问题,要么是流体动力学/传质问题。如果您从头开始求解,您将从欧拉(固定控制体积)视点的质量和动量守恒方程开始。

这是一个瞬态问题,因此您需要执行积分以将状态从时间 t(n) 推进到 t(n+1)。您显示了一个网格,但没有说明您如何及时解决。您尝试过哪种集成方案?明确的?隐式?曲柄-尼科尔森?如果您不知道,则说明您没有正确解决问题。

关于这个主题,我非常喜欢的一本书是 SW Patankar 的“数值传热和流体流动”。现在有点过时了,但我喜欢这种治疗方法。29 年后它仍然很好,但自从我阅读这个主题以来,可能会有更好的文本。我认为对于第一次研究它的人来说这是平易近人的。

于 2009-01-25T22:37:47.963 回答
5

在您给出的示例中,您的第二阶段的核心为 1。通常扩散需要浓度梯度,因此大多数与扩散相关的技术不会在下一次迭代中改变中间的 1(也不会在第一次迭代后达到那种状态,但是一旦你已经得到一个相等值的块)。但正如您帖子上的评论者所说,这不太可能是网络运动的原因。减少气体可能是边缘效应,但也可能是舍入误差的问题 - 将 cpu 设置为平均舍入一半,然后计算气体并不时应用修正。

于 2009-01-25T22:37:14.437 回答
2

看起来您正在尝试使用 Neumann 边界条件(边缘绝缘)为热方程实现有限差分求解器。有很多关于这种事情的文献。有限差分法的维基百科页面描述了一种简单但稳定的方法,但适用于狄利克雷边界条件(边缘处的恒定密度)。修改边界条件的处理应该不会太困难。

于 2009-01-25T22:45:55.513 回答
1

看起来你想要的是一种平滑算法,通常用于 Photoshop 等程序或老式演示效果,比如这个简单的火焰效果

无论您使用什么算法,它都可能帮助您对数组进行双重缓冲。

典型的平滑效果类似于:

begin loop forever
    For every x and y
    {
        b2[x,y]  = (b1[x,y] + (b1[x+1,y]+b1[x-1,y]+b1[x,y+1]+b1[x,y-1])/8) / 2
    }
    swap b1 and b2
end loop forever
于 2009-01-26T00:25:58.150 回答
1

请参阅Tom Forsyth 的 Game Programming Gems 文章。看起来它满足您的要求,但如果没有,那么它至少应该给您一些想法。

于 2009-01-26T01:46:21.153 回答
1

为简单起见,这里有一个 1D 解决方案:

初始设置在原点 () 处的浓度为 9,在所有其他正坐标和负坐标处浓度为 0。

初始状态:0 0 0 0 (9) 0 0 0 0

寻找下一个迭代值的算法是从原点开始,并与相邻邻居的平均电流浓度。原点值是一个边界情况,平均是考虑原点值和它的两个邻居同时进行的,即3个值的平均值。所有其他值在 2 个值之间有效平均。

迭代 1 后:0 0 0 3 (3) 3 0 0 0

迭代 2 后:0 0 1.5 1.5 (3) 1.5 1.5 0 0

迭代 3 后:0 .75 .75 2 (2) 2 .75 .75 0

迭代 4 后: .375 .375 1.375 1.375 (2) 1.375 1.375 .375 .375

您在循环中执行这些迭代。每 n 次迭代输出状态。您可以引入一个时间常数来控制多少次迭代代表一秒的时钟时间。这也是整数坐标表示的长度单位的函数。对于给定的硬件系统,您可以根据经验调整此值。您还可以引入稳态容差值来控制程序何时说“所有相邻值都在此容差范围内”或“迭代之间没有值更改超过此容差”,因此算法已达到稳态解。

于 2009-01-26T19:55:19.617 回答
0

给定起始浓度的每次迭代的浓度可以通过下式获得:

concentration = startingConcentration/(2*iter + 1)**2

iter 是时间迭代。所以对于你的例子。

startingConcentration = 9
iter = 0
concentration = 9/(2*0 + 1)**2 = 9

iter = 1
concentration = 9/(2*1 + 1)**2 = 1

iter = 2
concentration = 9/(2*2 + 1)**2 = 9/25 = .35

您可以在每个“时间步长”之后设置数组的值

于 2009-01-26T03:00:02.067 回答