2013-10-10 1 views
1

Я использую это article, чтобы написать приложение для моделирования жидкости. Мне не удается реализовать внутренние границы. Насколько я знаю, когда я устанавливаю границы (в функции 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; 
    } 
    } 
} 

К сожалению, дым поглощается и исчезает при контакте с поверхностью границы.
Мой математический фон недостаточен для понимания каждой части расчета, поэтому я буду очень благодарен, если кто-то укажет мне правильное направление.

+0

Не могли бы вы объяснить это немного подробнее? 'set_bnd' определен в документе. Каким должен быть ваш код для каких ячеек? Клетки, прилегающие к пограничным ячейкам (что означает ячейки с по меньшей мере одной гранью, эквивалентной границе стены), не должны обрабатываться специально, насколько я знаю. – EverythingRightPlace

ответ

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 

} 

Per книги (рабочая):
В первом контуре устанавливается сверху, справа, снизу и левые граничные ячейки. Поскольку для них существует только одна соседняя ячейка, которая не связана ячейкой, получает ее значение. (Я не знаю, почему его противоположность для U и то же значение для V)

После первого цикла устанавливаются значения угловых границ. Здесь они получают средние значения из своих соседних ячеек (думаю, поскольку нет соседней ячейки, которая не является границей, они используют граничные ячейки).

Mine, не работает должным образом:
если (б!) Возвращение - игнорирует расчеты плотности и обновления только скорость.
Петля вычисляет значения для всех граничных ячеек (опять же, средние значения из соседних ячеек, которые сами не являются границами). Я получаю почти реалистический результат от этих методов, но есть большие потери в плотности и некоторые ошибки со слишком большими границами, где жидкость полностью исчезает.

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), который указывает на клетки, которые являются границами. Работает с одной или несколькими пограничными областями, но они должны быть как минимум 3 ячейки в ширину и высоту.