- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
以下流体模拟是对paper by Stam的翻译.真正可怕的事情发生了。每次程序以较低的 DIFF=0.01
运行时,值开始时很小,然后迅速扩大,或“膨胀”。我仔细检查了数学例程。由于代码以一个 0.5
开始,从数学上讲它是乘以和添加一堆零,因此最终结果应该接近零密度和其他 vector 。
代码很长,所以我把它分成 block 并删除了多余的代码。减去所有开头和 SDL 代码,只有大约 120 行。我花了几个小时尝试更改但无济于事,因此非常感谢您的帮助。
经过一些实验后,我相信当 DIFF
设置得太低时可能会出现一些浮点错误。当值从 0.01
增加到 0.02
时,值不会爆炸。不过,我认为这不是全部问题。
需要明确的是,1201ProgramAlarm 和 vidstige 的当前答案并未解决问题。
粗体部分为重要部分,其余为完整性。
开始的东西,跳过
#include <SDL2/SDL.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define IX(i,j) ((i)+(N+2)*(j))
using namespace std;
// Constants
const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 600; // Should match SCREEN_WIDTH
const int N = 20; // Grid size
const int SIM_LEN = 1000;
const int DELAY_LENGTH = 40; // ms
const float VISC = 0.01;
const float dt = 0.1;
const float DIFF = 0.01;
const bool DISPLAY_CONSOLE = false; // Console or graphics
const bool DRAW_GRID = false; // implement later
const int nsize = (N+2)*(N+2);
数学例程 扩散例程除以 1+4*a
。这是否意味着密度必须 <= 1?
void set_bnd(int N, int b, vector<float> &x)
{
// removed
}
inline void lin_solve(int N, int b, vector<float> &x, vector<float> &x0, float a, float c)
{
for (int k=0; k<20; k++)
{
for (int i=1; i<=N; i++)
{
for (int j=1; j<=N; j++)
{
x[IX(i,j)] = (x0[IX(i,j)] + a*(x[IX(i-1,j)]+x[IX(i+1,j)]+x[IX(i,j-1)]+x[IX(i,j+1)])) / c;
}
}
set_bnd ( N, b, x );
}
}
// Add forces
void add_source(vector<float> &x, vector<float> &s, float dt)
{
for (int i=0; i<nsize; i++) x[i] += dt*s[i];
}
// Diffusion with Gauss-Seidel relaxation
void diffuse(int N, int b, vector<float> &x, vector<float> &x0, float diff, float dt)
{
float a = dt*diff*N*N;
lin_solve(N, b, x, x0, a, 1+4*a);
}
// Backwards advection
void advect(int N, int b, vector<float> &d, vector<float> &d0, vector<float> &u, vector<float> &v, float dt)
{
float dt0 = dt*N;
for (int i=1; i<=N; i++)
{
for (int j=1; j<=N; j++)
{
float x = i - dt0*u[IX(i,j)];
float y = j - dt0*v[IX(i,j)];
if (x<0.5) x=0.5; if (x>N+0.5) x=N+0.5;
int i0=(int)x; int i1=i0+1;
if (y<0.5) y=0.5; if (y>N+0.5) y=N+0.5;
int j0=(int)y; int j1=j0+1;
float s1 = x-i0; float s0 = 1-s1; float t1 = y-j0; float t0 = 1-t1;
d[IX(i,j)] = s0*(t0*d0[IX(i0,j0)] + t1*d0[IX(i0,j1)]) +
s1*(t0*d0[IX(i1,j0)] + t1*d0[IX(i1,j1)]);
}
}
set_bnd(N, b, d);
}
}
void project(int N, vector<float> &u, vector<float> &v, vector<float> &p, vector<float> &div)
{
float h = 1.0/N;
for (int i=1; i<=N; i++)
{
for (int j=1; j<=N; j++)
{
div[IX(i,j)] = -0.5*h*(u[IX(i+1,j)] - u[IX(i-1,j)] +
v[IX(i,j+1)] - v[IX(i,j-1)]);
p[IX(i,j)] = 0;
}
}
set_bnd(N, 0, div); set_bnd(N, 0, p);
lin_solve(N, 0, p, div, 1, 4);
for (int i=1; i<=N; i++)
{
for (int j=1; j<=N; j++)
{
u[IX(i,j)] -= 0.5*(p[IX(i+1,j)] - p[IX(i-1,j)])/h;
v[IX(i,j)] -= 0.5*(p[IX(i,j+1)] - p[IX(i,j-1)])/h;
}
}
set_bnd(N, 1, u); set_bnd(N, 2, v);
}
密度和速度求解器
// Density solver
void dens_step(int N, vector<float> &x, vector<float> &x0, vector<float> &u, vector<float> &v, float diff, float dt)
{
add_source(x, x0, dt);
swap(x0, x); diffuse(N, 0, x, x0, diff, dt);
swap(x0, x); advect(N, 0, x, x0, u, v, dt);
}
// Velocity solver: addition of forces, viscous diffusion, self-advection
void vel_step(int N, vector<float> &u, vector<float> &v, vector<float> &u0, vector<float> &v0, float visc, float dt)
{
add_source(u, u0, dt); add_source(v, v0, dt);
swap(u0, u); diffuse(N, 1, u, u0, visc, dt);
swap(v0, v); diffuse(N, 2, v, v0, visc, dt);
project(N, u, v, u0, v0);
swap(u0, u); swap(v0, v);
advect(N, 1, u, u0, u0, v0, dt); advect(N, 2, v, v0, u0, v0, dt);
project(N, u, v, u0, v0);
}
我考虑过 floating-point inconsistencies , 但在用 -ffloat-store
编译后问题仍然存在。
最佳答案
此问题与 add_source()
中缺少规范化有关。
当你的密度变得足够稳定时(x0
与 x
的分布非常相似,达到比例因子),然后 add_source()
有效地将 x
乘以大约 1+dt
,导致您的指数爆炸。 DIFF
的高值通过在 lin_solve()
中使 x
比 x0
更重来掩盖这种影响,这意味着有效乘数接近 1
,但仍高于 1。
这样的效果就是每次迭代都会增加更多的质量。如果它不能在边缘足够快地“展开”,它就会开始堆积起来。一旦密度变得完全静止,它的质量将以指数速率增加,指数速率由 1+dt/(4a)
决定。
根据您给定的设置 (dt=0.1, a=0.1*0.01*20*20=0.4
),这是 1+0.1/1.6 ~ 1.06
。
修复是在 add_source 中规范化:
x[i] = (x[i]+dt*s[i])/(1.0f+dt);
,或计算 lin_solve()
的 c
参数为 1+4*a+dt
。两者都会迫使质量下降。
关于c++ - 流体模拟 "Blows Up",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33950351/
以下流体模拟是对paper by Stam的翻译.真正可怕的事情发生了。每次程序以较低的 DIFF=0.01 运行时,值开始时很小,然后迅速扩大,或“膨胀”。我仔细检查了数学例程。由于代码以一个 0.
我正在编写一些代码来获得生成的线程以从 C++ 调用静态 Java 方法。 如果放置在来自 Java 的 native 调用中,调用该方法的位可以正常工作,但不能来自带有附加 JNIEnv 的线程。
我需要快速开发一个 iOS 应用程序来检测用户对麦克风的打击。这必须是一场挑战游戏,两名玩家必须依次向 iPhone 麦克风吹气。分贝值应以米或公里为单位进行测量和转换,以便我确定优胜者。 “吹得更远
众所周知,Facebook 文档并不是最好的。它内部不一致,不断变化,充满了损坏的链接,并且经常过时或完全错误。我搜索了又搜索,似乎找不到一个非常简单问题的答案:您能否获取开放图形对象实例的见解数据,
我尝试了几个版本的简单谓词,该谓词从超逻辑宇宙中提取随机值并将它们放入列表中。我假设带有累加器的版本是 tail-call optimized ,因为在递归调用之后什么也没有发生,所以存在优化的路径,
已开发的新应用程序大量使用 Web 服务。我们开始定期遇到内存不足异常(随着使用量的增加)。在查看内存转储时,我注意到有大量相同大小的 byte[]。查看这些 byte[] 的句柄,我注意到它们被 S
MPMoviePlayerController 播放器在按下完成按钮后永久隐藏播放器控件。 我有一个带有 moviePlayer.controlStyle = MPMovieControlStyleE
问题:使用有限差分迭代求解拉普拉斯方程 div2(u)=0。 边界条件:u(x,0)=1 u(x,1)=u(0,y)=u(1,y)=0 算法是: u[i,j]= 0.25 * (u[i,j-1] +
所以 Qt 在 windows 上是用/Zc:wchar_t- 编译的。这意味着 wchar_t 不是某些内部类型(我认为是 __wchar_t)的 typedef,而是 unsigned short
我尝试将 jpg-images 作为一长串图片框加载到表格布局面板中。图像列表应该可以平滑滚动,即没有闪烁或可见的模糊或抖动。大约有 300 张图片,每张图片的大小约为 150kb (600px x
在这一点上,我对高尔夫不是很熟悉,但一定有一种方法来配置错误处理。它不能总是在没有的时候就吓坏了;当你打字到一半的时候,你的SCSS,对吗?。我遗漏了什么?对此进行了研究,但似乎找不到答案。这真的很令
以下代码在 Chrome 和 Firefox 中都能正常工作。在 IE 9 中,附加选项,但文本始终为空白。 function populateDeveloperDropDownViaSkillPro
我是一名优秀的程序员,十分优秀!