1

この記事を使用して、流体シミュレーション アプリケーションを作成しています。内側の境界を実装できません。私が知っている限り、境界の内側にある各セルの境界を ( set_bnd関数で) 設定しているとき、次のように隣接する非境界セルから平均値を計算する必要があります。

for (i = 0 ; i < n ; i++)
{
  for (j = 0 ; j < n ; j++)
  {
     if (isBoundary(i,j)
     {
        sum = 0;
        count = 0;
        if (!isBoundary(i+1,j) {
           sum += x[i+1][j];
        }
        if (!isBoundary(i-1,j) {
           sum += x[i-1][j];
        }
        if (!isBoundary(i,j+1) {
           sum += x[i][j+1];
        }
        if (!isBoundary(i,j-1) {
           sum += x[i-1][j];
        }
        x[i][j] = sum / 4;
     }
  }
}

残念ながら、煙は吸収され、境界面に接触して消えます。
私の数学のバックグラウンドは計算のすべての部分を理解するのに十分ではないので、誰かが私に正しい方向性を示してくれたらとても感謝しています.

4

2 に答える 2

0

私はなんとか解決策を見つけることができました。これは、同じ問題を抱えている可能性のある人々のためのものです

void set_bnd ( int N, int b, float * x, int * insideBound )
{
    int i, j;
    float sum, tmp;
    int count;

    for ( i=1 ; i<=N ; i++ ) {
        x[IX(0  ,i)] = b==1 ? -x[IX(1,i)] : x[IX(1,i)];
        x[IX(N+1,i)] = b==1 ? -x[IX(N,i)] : x[IX(N,i)];
        x[IX(i,0  )] = b==2 ? -x[IX(i,1)] : x[IX(i,1)];
        x[IX(i,N+1)] = b==2 ? -x[IX(i,N)] : x[IX(i,N)];
    }
    x[IX(0  ,0  )] = 0.5f*(x[IX(1,0  )]+x[IX(0  ,1)]);
    x[IX(0  ,N+1)] = 0.5f*(x[IX(1,N+1)]+x[IX(0  ,N)]);
    x[IX(N+1,0  )] = 0.5f*(x[IX(N,0  )]+x[IX(N+1,1)]);
    x[IX(N+1,N+1)] = 0.5f*(x[IX(N,N+1)]+x[IX(N+1,N)]);

    if (!b) return;

    for ( i=1 ; i<=N ; i++ ) {
        for ( j=1 ; j<=N ; j++ ) {
            sum = 0.0f;
            count = 0;
            if (insideBound[IX(i,j)] == 1)
            {
                if (insideBound[IX(i-1,j)] != 1)
                {
                    count++;
                    if (b == 2)
                        tmp = -x[IX(i-1,j)];
                    else 
                        tmp = x[IX(i-1,j)];

                    sum = sum + tmp;
                }

                if (insideBound[IX(i+1,j)] != 1)
                {
                    count++;
                    if (b == 2)
                        tmp = -x[IX(i+1,j)];
                    else
                        tmp =  x[IX(i+1,j)];
                    sum = sum + tmp;
                } 

                if (insideBound[IX(i,j-1)] != 1)
                {
                    count++;
                    if (b == 1)
                        tmp = - x[IX(i, j-1)];
                    else 
                        tmp =  x[IX(i, j-1)];
                    sum = sum + tmp;
                } 

                if (insideBound[IX(i,j+1)] != 1)
                {
                    count++;
                    if (b == 1)
                        tmp = -x[IX(i, j+1)];
                    else 
                        tmp = x[IX(i, j+1)];
                    sum = sum + tmp;
                } 

                if (count > 0)
                {
                    x[IX(i,j)] = -sum / count;
                } else {
                    x[IX(i,j)]  = 0;
                }
            }
        }
    }
}

insideBoundは、境界であるセルを示すブール配列 (0,1) です。1 つまたは複数の境界領域で機能しますが、少なくとも 3 セルの幅と高さが必要です。

于 2013-10-15T18:19:55.677 に答える
0

さらに説明するコードを次に示します。
insideBoundは配列です (1 - 境界、0 - 空、流体は通過できます)

#define FOR_EACH_CELL for ( i=1 ; i<=N ; i++ ) { for ( j=1 ; j<=N ; j++ ) {


void set_bnd ( int N, int b, float * x, int * insideBound )
{
int i, j;
float sum;
int count;

for ( i=1 ; i<=N ; i++ ) {
    x[IX(0  ,i)] = b==1 ? -x[IX(1,i)] : x[IX(1,i)];
    x[IX(N+1,i)] = b==1 ? -x[IX(N,i)] : x[IX(N,i)];
    x[IX(i,0  )] = b==2 ? -x[IX(i,1)] : x[IX(i,1)];
    x[IX(i,N+1)] = b==2 ? -x[IX(i,N)] : x[IX(i,N)];
}
x[IX(0  ,0  )] = 0.5f*(x[IX(1,0  )]+x[IX(0  ,1)]);
x[IX(0  ,N+1)] = 0.5f*(x[IX(1,N+1)]+x[IX(0  ,N)]);
x[IX(N+1,0  )] = 0.5f*(x[IX(N,0  )]+x[IX(N+1,1)]);
x[IX(N+1,N+1)] = 0.5f*(x[IX(N,N+1)]+x[IX(N+1,N)]);

if (!b) return;

FOR_EACH_CELL
    sum = 0.0f;
    count = 0;
    if (insideBound[IX(i,j)] == 1)
    {
        if (insideBound[IX(i-1,j)] != 1)
        {
            count++;
            sum = sum + x[IX(i-1,j)];
        }

        if (insideBound[IX(i+1,j)] != 1)
        {
            count++;
            sum = sum + x[IX(i+1,j)];
        }

        if (insideBound[IX(i,j-1)] != 1)
        {
            count++;
            sum = sum + x[IX(i, j-1)];
        }

        if (insideBound[IX(i,j+1)] != 1)
        {
            count++;
            sum = sum + x[IX(i, j+1)];
        }

        if (count > 0)
        {
            x[IX(i,j)] = -sum / count;
        } else {
            x[IX(i,j)]  = 0;
        }


    }

END_FOR

}

ブックごと (作業中):
最初のループでは、上、右、下、左の境界セルが設定されます。それらには、バインドされていない隣接セルが1つしかないため、セルはその値を取得します。(なぜUが反対でVが同じ値なのかわかりません)

最初のループの後、角の境界値が設定されます。ここでは、隣接するセルから平均値を取得します(境界ではない隣接セルがないため、境界セルを使用していると思います)。

私の場合、正しく機能していません:
if (!b) return - 密度の計算を無視し、速度のみを更新します。
ループは、すべての境界セルの値を計算します (ここでも、境界自体ではない隣接セルからの平均値)。この方法でほぼ現実的な結果が得られますが、密度が大きく失われ、流体が完全に消えてしまう境界が大きすぎるというバグがいくつかあります。

于 2013-10-13T11:41:44.357 に答える