Алгоритм моделирования расширяющихся газов на двумерной сетке - PullRequest
4 голосов
/ 26 января 2009

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

Например, данное состояние может быть: (для простоты используем целые)

исходное состояние

00000
00000
00900
00000
00000

состояние после 1 прохода алгоритма

00000
01110
01110
01110
00000

еще один шаг должен дать сетку 5x5, содержащую значение 0,36 (9/25).
Я попробовал это на бумаге, но как бы я ни пытался, я не могу понять, как это сделать.

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

Ответы [ 7 ]

6 голосов
/ 26 января 2009

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

Это временная проблема, поэтому вам нужно выполнить интегрирование, чтобы продвинуть состояние от времени t (n) до t (n + 1). Вы показываете сетку, но ничего о том, как вы решаете во времени. Какую схему интеграции вы пробовали? Явный? Неявные? Crank-Николсона? Если вы не знаете, вы неправильно подходите к проблеме.

Одна книга, которая мне действительно понравилась на эту тему, была S.W. Патанкара "Числовой теплообмен и поток жидкости" . Сейчас оно немного устарело, но мне понравилось лечение. Это все еще хорошо после 29 лет, но могут быть лучшие тексты, так как я читал на эту тему. Я думаю, что это доступно для кого-то, кто изучает это впервые.

5 голосов
/ 26 января 2009

В приведенном вами примере ваша вторая ступень имеет ядро ​​1. Обычно диффузия требует градиента концентрации, поэтому большинство методов, связанных с диффузией, не изменят 1 в середине на следующей итерации (и при этом они не дойдут до этого состояния после первой, но это будет немного легче увидеть, как только вы получил блок равных значений). Но, как говорят комментаторы в вашем посте, это вряд ли является причиной чистого движения. Уменьшение количества газа может быть краевым эффектом, но также может быть связано с ошибками округления - установите процессор равным половине четного, и суммируйте газ и применяйте коррекцию время от времени.

2 голосов
/ 26 января 2009

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

1 голос
/ 26 января 2009

Вот решение в 1D для простоты:

Начальная установка имеет концентрацию 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 системы вы можете настроить это значение опытным путем. Вы также можете ввести значение допуска установившегося состояния для управления, когда программа говорит, что «все соседние значения находятся в пределах этого допуска» или «значение не изменилось между итерациями более чем на это отклонение», и поэтому алгоритм достиг решения для устойчивого состояния. *

1 голос
/ 26 января 2009

См. Статья Тома Форсайта "Gem для программирования игр" . Похоже, он отвечает вашим требованиям, но если нет, то он должен хотя бы дать вам некоторые идеи.

1 голос
/ 26 января 2009

Похоже, что вы хотите, это что-то вроде алгоритма сглаживания, часто используемого в таких программах, как Photoshop, или демонстрационных эффектов старой школы, таких как простой Flame Effect .

Какой бы алгоритм вы ни использовали, он, вероятно, поможет вам двойной буфер ваш массив.

Типичный эффект сглаживания будет примерно таким:

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
0 голосов
/ 26 января 2009

Концентрация для каждой итерации с учетом начальной концентрации может быть получена с помощью уравнения:

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

Вы можете установить значение массива после каждого «временного шага»

...