在二维网格上模拟膨胀气体的算法

发布于 2024-07-11 19:39:34 字数 544 浏览 12 评论 0原文

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

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

起始状态

00000
00000
00900
00000
00000

00000算法 1 次通过后的

状态
01110
01110
01110
00000

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

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

I have a simple program, at it's heart is a two dimensional array of floats, supposedly representing gas concentrations, I have been trying to come up with a simple algorithm that will model the gas expanding outwards, like a cloud, eventually ending up with the same concentration of the gas everywhere across the grid.

For example a given state progression could be:
(using ints for simplicity)

starting state

00000
00000
00900
00000
00000

state after 1 pass of algorithm

00000
01110
01110
01110
00000

one more pas should give a 5x5 grid all containing the value 0.36 (9/25).
I've tried it out on paper but no matter how I try, I cant get my head around the algorithm to do this.

So my question is, how should I set about trying to code this algorithm? I've tried a few things, applying a convolution, trying to take each grid cell in turn and distributing it to its neighbours, but they all end up having undesirable effects, such as ending up eventually with less gas than I originally started with, or all of gas movement being in one direction instead of expanding outwards from the centre. I really can't get my head around it at all and would appreciate any help at all.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

梦里兽 2024-07-18 19:39:34

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

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

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

It's either a diffusion problem if you ignore convection or a fluid dynamics/mass transfer problem if you don't. You would start with equations for conservation of mass and momentum for an Eulerian (fixed control volume) viewpoint if you were solving from scratch.

It's a transient problem, so you need to perform an integration to advance the state from time t(n) to t(n+1). You show a grid, but nothing about how you're solving in time. What integration scheme have you tried? Explicit? Implicit? Crank-Nicholson? If you don't know, you're not approaching the problem correctly.

One book that I really liked on this subject was S.W. Patankar's "Numerical Heat Transfer and Fluid Flow". It's a little dated now, but I liked the treatment. It's still good after 29 years, but there might be better texts since I was reading on the subject. I think it's approachable for somebody looking into it for the first time.

沉鱼一梦 2024-07-18 19:39:34

在您给出的示例中,您的第二级的核心为 1。 通常扩散需要浓度梯度,因此大多数扩散相关技术不会在下一次迭代时改变中间的 1(它们也不会在第一次迭代后达到该状态,但一旦你得到一个相同值的块)。 但正如您帖子的评论者所说,这不太可能是网络运动的原因。 减少 Gas 可能是边缘效应,但也可能是舍入误差的问题 - 将 CPU 设置为均匀舍入一半,然后总计 Gas 并时不时地应用校正。

In the example you give, your second stage has a core of 1's. Usually diffusion requires a concentration gradient, so most diffusion related techniques won't change the 1 in the middle on the next iteration (nor would they have got to that state after the first one, but it's a bit easier to see once you've got a block of equal values). But as the commenters on your post say, that's not likely to be the cause of a net movement. Reducing the gas may be edge effects, but can also be a question of rounding errors - set the cpu to round half even, and total the gas and apply a correction now and again.

↘紸啶 2024-07-18 19:39:34

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

It looks like you're trying to implement a finite difference solver for the heat equation with Neumann boundary conditions (insulation at the edges). There's a lot of literature on this kind of thing. The Wikipedia page on finite difference method describes a simple but stable method, but for Dirichlet boundary conditions (constant density at edges). Modifying the handling of the boundary conditions shouldn't be too difficult.

一百个冬季 2024-07-18 19:39:34

看起来您想要的是平滑算法之类的东西,通常在 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

It looks like what you want is something like a smoothing algorithm, often used in programs like Photoshop, or old school demo effects, like this simple Flame Effect.

Whatever algorithm you use, it will probably help you to double buffer your array.

A typical smoothing effect will be something like:

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
前事休说 2024-07-18 19:39:34

请参阅 Tom Forsyth 的《游戏编程宝石》文章。 看起来它满足您的要求,但如果没有,那么它至少应该给您一些想法。

See Tom Forsyth's Game Programming Gems article. Looks like it fulfils your requirements, but if not then it should at least give you some ideas.

活泼老夫 2024-07-18 19:39:34

为简单起见,下面是一维解决方案:

初始设置在原点 () 处浓度为 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次迭代输出状态。 您可以引入一个时间常数来控制代表一秒墙上时钟时间的迭代次数。 这也是整数坐标代表的长度单位的函数。 对于给定的 H/W 系统,您可以凭经验调整该值。 您还可以引入稳态容差值来控制程序何时显示“所有邻居值都在此容差范围内”或“迭代之间没有值的变化超过此容差”,因此算法已达到稳态解。

Here's a solution in 1D for simplicity:

The initial setup is with a concentration of 9 at the origin (), and 0 at all other positive and negative coordinates.

initial state:
0 0 0 0 (9) 0 0 0 0

The algorithm to find next iteration values is to start at the origin and average current concentrations with adjacent neighbors. The origin value is a boundary case and the average is done considering the origin value, and its two neighbors simultaneously, i.e. average among 3 values. All other values are effectively averaged among 2 values.

after iteration 1:
0 0 0 3 (3) 3 0 0 0

after iteration 2:
0 0 1.5 1.5 (3) 1.5 1.5 0 0

after iteration 3:
0 .75 .75 2 (2) 2 .75 .75 0

after iteration 4:
.375 .375 1.375 1.375 (2) 1.375 1.375 .375 .375

You do these iterations in a loop. Outputting the state every n number of iterations. You may introduce a time constant to control how many iterations represent one second of clock-on-the-wall time. This is also a function of what length units the integer coordinates represent. For a given H/W system, you can tune this value empirically. You may also introduce a steady state tolerance value to control when the program says " all neighbor values are within this tolerance" or "no value changed between iterations by more than this tolerance" and so the algorithm has reached a steady state solution.

他是夢罘是命 2024-07-18 19:39:34

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

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

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

The concentration for each iteration given a starting concentration can be obtained by the equation:

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

iter is the time iteration. So for your example.

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

you can set the value of the array after each "time step"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文