Каковы хорошие типы данных для неструктурированного кода FVM CFD на основе ячеек?


12

Мне интересны советы по созданию эффективных структур данных для просмотра ячеек в неструктурированных CFD с конечным объемом на основе ячеек.

Один из примеров, с которыми я столкнулся (в коде dolfyn cfd ), выглядит следующим образом (я покажу соответствующий сегмент) list } Итак, у нас есть массив NFaces, в котором хранится количество граней для каждой ячейки. Затем массив CFace, который отображает локальный номер лица в глобальный номер лица.

\begin{listing}do ip=1,Ncel         ...         do j=1,NFaces(ip)           k   = CFace(ip,j)           ipp = Face(k)%cell1           inn = Face(k)%cell2           if( inn > 0 )then             ! internal\end{listing}

Код основан на лице, поэтому существует тип данных лица, в котором хранится серийный номер двух ячеек, лежащих между Face (k)% cell1 и Face (k)% cell2.

Любые комментарии по этому поводу или предложения по альтернативному подходу приветствуются.

Ответы:


9

Показанная вами структура является обычным выбором и эквивалентна хранению смежности граней ячеек в матричном формате CSR с выделенными ячейками границы в специальном месте. Тем не менее, обратите внимание, что методы FV также могут быть сформулированы так, чтобы они полностью или почти полностью состояли из обхода лица, при котором каждое лицо посещается только один раз (реконструкция по центроидной / квадратурной точке лица с обеих сторон, решение проблемы Римана, распределение потока обратно в остаток на ячейках ). Вы можете «подделать» это, используя обход на основе ячеек и пропуская любые две ячейки, которые находятся ниже «диагонали» в разреженной матрице, но популярной альтернативой является хранение(leftCell, rightCell) = support(face), в этом случае лица становятся первоклассными объектами. Это полезно, потому что вам обычно нужно место для хранения квадратурных точек лица (центроидов), нормалей лица. Вы также можете поместить детали реконструкции (например, наименьшие квадраты) в структуры данных на основе лица. Обход грани, по-видимому, удобен для векторизации, поскольку все размеры являются регулярными, но, с другой стороны, выходы перекрываются, поэтому вам необходимо организовать обход, чтобы не помещать его во внутренний цикл. При такой более ориентированной на грани структуре данных естественно упорядочить номера граней так, чтобы каждый тип граничного условия мог применяться с использованием непрерывного обхода граней (также дружественных к векторизации).

Если вы выберете эту структуру данных, не забудьте отсортировать грани так, чтобы при повторном использовании данные ячейки в кеше использовались как можно чаще. См. Любой из документов PETSc-FUN3D для анализа производительности упорядочения лица и связанных оптимизаций.


Если вы перебираете грани, вам нужно будет получить информацию от leftCell и rightCell для вычисления потоков, скажем, у face 1 есть leftCell 1 и rightCell 10, у face 2 есть leftCell 6 и rightCell 31, ... тем самым перепрыгивая через память , Как это было бы дружественным к векторизации?
Крис

Как упоминалось выше (и обсуждалось в статьях PETSc-FUN3D), вы приказываете граням повторно использовать кэш. Результат похож на «односторонний» обход ячейки, при котором каждое лицо посещается только один раз.
Джед Браун

3

Я знаю, что на этот вопрос уже дан ответ, но вот похожее хранилище циклов на основе одного лица, которое реализовано в библиотеке OpenFOAM C ++:

Каждая ячейка имеет индекс (ID) в cellList. Для всех лиц определены два списка: «лицо внутреннего владельца» и «лицо соседа». Длина обоих списков граней соответствует количеству внутренних граней в сетке. Владелец лица будет ячейкой с более низким идентификатором в cellList (напротив для лица соседа). Граничные грани записываются в последнюю очередь и имеют ориентированные наружу нормали (из области решения) и, конечно, только одну ячейку-владельца. Нормальная область лица ориентирована так, чтобы она смотрела наружу из ячейки владельца в соседнюю ячейку.

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

Поскольку граничные грани агломерированы в патчи, межпроцессное взаимодействие определяется для связанных (процессорных) патчей и предопределено. Это означает, что, как только петля пересекает граничную сетку, функции доступа верхнего уровня вызывают обернутые вызовы MPI, делая такой код «автоматически» распараллеленным, если он опирается на вышеописанное соединение на основе лица.


Нет проблем, я рад видеть, что это описание кому-то пригодится .. :) Вы тоже работаете с OpenFOAM?
tmaric

Я привык, немного в прошлом. Я обычно стараюсь держаться подальше от принятых тенденций и стараюсь изобретать велосипед. Это мой Дао.
Johntra Volta

1
Ваш Дао является противоположностью Дао Информатики: «Не изобретай колесо». Но я могу это понять, это привлекательно делать вещи с нуля! :)
tmaric
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.