Границы моделирования жидкости и адвект

Это моделирование жидкости основано на статье Stam. На странице 7 он описывает основную идею адвекции:

Начните с двух сеток: одна содержит значения плотности с предыдущего временного шага, а вторая - новые значения. Для каждой ячейки сетки последнего мы отслеживаем положение центра ячейки в обратном направлении через поле скоростей. Затем мы линейно интерполируем из сетки предыдущих значений плотности и присваиваем это значение текущей ячейке сетки.

Код Advect. Две сетки плотности: d и d0, u и v - компоненты скорости, dt - временной шаг, N (глобальный) - размер сетки, b можно игнорировать:

void advect(int b, vfloat &d, const vfloat &d0, const vfloat &u, const vfloat &v, float dt, std::vector<bool> &bound)
{
    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(b, d, bound);
}

Этот метод краток и работает достаточно хорошо, но мне сложно понять реализацию границ объекта, потому что значения отслеживаются в обратном направлении и интерполируются. Мое текущее решение - просто вытолкнуть плотность за границы, если рядом с ней есть пустое пространство (или пробелы), но это неточно и вызывает увеличение плотности, особенно в углах и областях с диагональной скоростью. только визуально точный. Ищу "правильность" сейчас.

Соответствующие части моего граничного кода:

void set_bnd(const int b, vfloat &x, std::vector<bool> &bound)
{
    //...
    for (int i=1; i<=N; i++)
    {
        for (int j=1; j<=N; j++)
        {
            if (bound[IX(i,j)])
            {
                //...
                else if (b==0)
                {
                    // Distribute density from bound to surrounding cells
                    int nearby_count = !bound[IX(i+1,j)] + !bound[IX(i-1,j)] + !bound[IX(i,j+1)] + !bound[IX(i,j-1)];
                    if (!nearby_count) x[IX(i,j)] = 0;
                    else
                        x[IX(i,j)] = ((bound[IX(i+1,j)] ? 0 : x[IX(i+1,j)]) +
                                      (bound[IX(i-1,j)] ? 0 : x[IX(i-1,j)]) +
                                      (bound[IX(i,j+1)] ? 0 : x[IX(i,j+1)]) +
                                      (bound[IX(i,j-1)] ? 0 : x[IX(i,j-1)])) / surround;
                }
            }
        }
    }
}

bound - это вектор bools со строками и столбцами от 0 до N+1. Граничные объекты устанавливаются перед основным циклом путем установки координат ячейки в bound на 1.

В документе расплывчато говорится: «Тогда мы просто должны добавить некоторый код в set_bnd() процедуру, чтобы заполнить значения для занятых ячеек из значений их прямых соседей», что вроде того, что я делаю. Я ищу способ более точной реализации границ, то есть наличие не жидких твердых границ и, возможно, в конечном итоге поддержки границ для нескольких жидкостей. Визуальное качество намного важнее правильности физики.


person qwr    schedule 28.12.2015    source источник
comment
Вы можете опубликовать код установки для bound? Я предполагаю, что граничные ячейки - это строка 0, строка N + 1, столбец 0 и столбец N + 1 [из диаграммы в статье]? Кроме того, set_bnd имеет else if (b==0), а if для этого else [выше] отсутствует. Вы можете добавить еще немного? Я вижу некоторые проблемы [проблема, похожая на границы видеокадров и векторы движения], но прежде чем я попытаюсь ответить, я хотел бы получить немного больше информации. Кроме того, когда b ноль / ненулевое значение?   -  person Craig Estey    schedule 31.12.2015
comment
@CraigEstey Я обновил свой вопрос. Часть кода удалена, чтобы вопрос был более кратким; закомментированные части set_bnd относятся к граничным условиям, которые не нужны для вопроса. Полная версия моего кода находится здесь   -  person qwr    schedule 31.12.2015
comment
Из того, что я вижу в статье, вы хотите просто использовать непрерывность плотности, а не «отражать» ее от границы. Это должно означать (для простых случаев, описанных в статье), чтобы граничная ячейка была такой же, как и неграничная ячейка, с которой она имеет общую грань.   -  person lrm29    schedule 01.01.2016
comment
Я построил его и запустил [добавление одного шага, отладка и т. Д.]. Для прямоугольных границ внутренние области, очевидно, сплошные, но как вы хотите, чтобы края? (например, [i15, j20] твердое или жидкое?). Или, слева направо, какое последнее значение x жидкости 14 или 15? Полагаю, 14? Это влияет на вещи. Должен ли край твердого тела иметь ненулевые [интерполированные] значения плотности [или скорости]? Я полагаю, что нет? Как вы количественно оцениваете ошибки? Отрицательные значения плотности? Что-нибудь еще? Как определить неисправность визуально или численно из дампа консоли?   -  person Craig Estey    schedule 01.01.2016
comment
@CraigEstey В настоящее время края рассматриваются как плавные, но в идеале они должны быть твердыми. Думаю, я уже позаботился о скорости, поэтому сейчас проблема в плотности. Плохое - это в основном исчезновение плотности (не отталкивание) и области, создающие плотность там, где этого не должно быть. С самого начала эта симуляция делалась только для визуальной точности, так что пока она выглядит реалистично, этого достаточно.   -  person qwr    schedule 01.01.2016
comment
Заметил [сплошные] края как плавные - отсюда и мой вопрос. Можно было бы увеличить яркость на прямоугольнике на +1 каждый директ [т. Е. теперь по одному]. На мой взгляд, скорость должна отражаться под углом падения к стене? Я подумывал о замене вектора границ чем-то более сложным (например, связанный список фигур) и подавлении вычислений по внутренним точкам в твердых [расточительных / неточных?]). Я заметил появление серого налета в правом углу юго-востока - в этом проблема? В: Почему ваша обработка в set_bnd of b == 1 / b == 2 отличается от обработки Stam [в цикле выше]?   -  person Craig Estey    schedule 01.01.2016
comment
@CraigEstey В настоящее время я применяю метод Стама для граничной скорости для моих объектов: делая горизонтальную и вертикальную скорость отрицательными по сравнению с тем, чем они были бы, так что результирующий эффект равен нулю. Сплошные края плавные просто потому, что именно так они описаны в статье. Я не думаю, что замена вектора границ значительно увеличит производительность, и вектор - это самый простой способ. Проблема была в сером нарастании, но это было исправлено тем, что упоминал lrm29. Теперь вопрос не так важен, как я думал, теперь он о правильности.   -  person qwr    schedule 01.01.2016
comment
Что вы изменили, чтобы внедрить исправление Irm29 [похоже, я упал]? Я с подозрением относился к использованию near_count - это то, что вы изменили? Для меня верхний край прямоугольника должен работать как нижний край внешнего блока и т. Д. Альтернативным способом создания границ может быть просто список точек. Затем forall bpt in bound: bpt.i,bpt.j,bpt.xxx (например, предварительное вычисление большего количества данных, поэтому меньше if в цикле). Чтобы лучше видеть, я сделал сетку внизу цикла рендеринга: SDL_SetRenderDrawColor(renderer,100,100,0,0); SDL_RenderDrawRect(renderer,&r);, но некоторые линии имеют двойную ширину из-за округления   -  person Craig Estey    schedule 01.01.2016
comment
@CraigEstey Я обновил вопрос. Я надеюсь, что вы не потратили слишком много времени на то, чтобы возиться с моим кодом (или, если да, по крайней мере, это того стоило вам); Я не уверен, что вы сейчас делаете с границами, но я просто прошу изменить то, как advect делается   -  person qwr    schedule 01.01.2016
comment
Не стоит беспокоиться. Для меня я получил введение в SDL и могу добавить его в библиотеку оболочки gfx, которая у меня есть, которая в настоящее время поддерживает GTK3 / GDK3 [установка последней составляет примерно 20 пакетов]. Адвект Стама кажется очень похожим на то, что делается в сжатии видео [H.264] [векторы движения, макроблоки, ядра свертки и т. Д.]. Альтернативное вдохновение для вас? На этом этапе я собираюсь предположить, что вы один, но, просто любопытно, что не так с настоящей рекламой?   -  person Craig Estey    schedule 01.01.2016
comment
@CraigEstey Думаю, я просто ищу, как реализовать advect для работы с коллизиями вместо того, что я делаю сейчас. Текущий код выглядит визуально приемлемым со стационарными границами, но для расширения, такого как движущиеся границы, такие как две жидкости (огонь и воздух, вода и воздух), потребуется реальное решение для адвекта.   -  person qwr    schedule 01.01.2016
comment
@qwr Что вы имеете в виду под «правильным способом рекламы»? Все, что вам нужно, это убедиться, что нет адвекции через границу, и вы делаете это, делая градиент по ней равным нулю. Если вам действительно интересно, я бы порекомендовал попробовать OpenFOAM, правильный код CFD. Существует руководство по транспортировке скалярных величин что может оказаться полезным.   -  person lrm29    schedule 01.01.2016
comment
@qwr Вы можете получить более быструю и лучшую помощь на cfd-online.   -  person lrm29    schedule 01.01.2016


Ответы (2)


Ваш ответ исходит из физики, а не моделирования. Поскольку вы имеете дело с границами, ваше поле скорости должно удовлетворять граничному условию отсутствия проскальзывания Прандтля, которое просто говорит о том, что скорость на границе должна быть равна нулю. См. https://en.wikipedia.org/wiki/Boundary_layer для (много) дополнительной информации. . Если ваше поле скорости не соответствует этому критерию, у вас возникнут трудности, которые вы описываете, включая перенос массы обратно через границу, что является довольно серьезным нарушением модели.

Вы также должны знать, что этот код переноса не сохраняет плотность (по замыслу) и что закон сохранения фиксируется в конце. Вам нужно обратить внимание на этот шаг, поскольку разложение Ходжа векторного поля также имеет применимые граничные условия.

person eh9    schedule 04.01.2016
comment
Этот ответ полезен, но в конечном итоге не дает решения, если оно существует. - person qwr; 04.01.2016

Возможно, вас заинтересует «Искусство плавной анимации» Йоса Стэма (сентябрь 2015 г.). Вокруг стр. 69 он подробно обсуждает граничные условия..

Возможно, также представляет интерес: https://software.intel.com/en-us/articles/fluid-simulation-for-video-games-part-1/.

«The Perfect Storm» был некоторое время назад, поэтому теперь ваш гибкий симулятор должен быть либо очень большим, либо очень быстрым, либо очень детализированным. Желательно все три. Некоторые могут использовать графический процессор, если их вариант использования позволяет.

Может это поможет ..

person James Fremen    schedule 06.01.2016